Wie wählt man einen Unterschied für eine Spalte und einen in einer anderen Spalte aus?

29

Ich muss eine SQL-Datenbank abfragen, um alle unterschiedlichen Werte einer Spalte zu finden, und ich benötige einen beliebigen Wert aus einer anderen Spalte. Betrachten Sie beispielsweise die folgende Tabelle mit zwei Spalten, Schlüssel und Wert:

key     value
===     =====
one     test
one     another
one     value
two     goes
two     here
two     also
three   example

Ich möchte eine willkürlich ausgewählte Beispielzeile von jedem einzelnen Schlüssel zurückbekommen und vielleicht diese drei Zeilen erhalten:

key     value
===     =====
one     test
two     goes
three   example

Wie kann ich eine solche Abfrage in SQL formulieren?

WilliamKF
quelle
2
Welches DBMS (Oracle, SQL-Server, DB2, MySQL, Postgres)?
Ypercubeᵀᴹ
1
Es ist ein proprietäres System.
WilliamKF

Antworten:

33

Die einfachste Abfrage zum Schreiben ist für MySQL (mit nicht strengen ANSI-Einstellungen). Es wird die nicht standardmäßige Konstruktion verwendet:

SELECT key, value
FROM tableX
GROUP BY key ;

In den letzten Versionen (5.7 und 8.0+), in denen die strengen Einstellungen und ONLY_FULL_GROUP_BYdie Standardeinstellungen verwendet werden, können Sie die ANY_VALUE()in 5.7 hinzugefügte Funktion verwenden:

SELECT key, ANY_VALUE(value) AS value
FROM tableX
GROUP BY key ;

Für andere DBMS mit Fensterfunktionen (wie Postgres, SQL-Server, Oracle, DB2) können Sie diese wie folgt verwenden. Der Vorteil ist, dass Sie auch andere Spalten im Ergebnis auswählen können (neben dem keyund value):

SELECT key, value
FROM tableX
    ( SELECT key, value,
             ROW_NUMBER() OVER (PARTITION BY key 
                                ORDER BY whatever)     --- ORDER BY NULL
               AS rn                                   --- for example
      FROM tableX
    ) tmp 
WHERE rn = 1 ;

Für ältere Versionen der oben genannten und für alle anderen DBMS, eine allgemeine Methode, die fast überall funktioniert. Ein Nachteil ist, dass Sie mit diesem Ansatz keine anderen Spalten auswählen können. Ein weiterer Grund ist, dass Aggregatfunktionen in einigen DBMS (wie Bit, Text, Blobs) mit einigen Datentypen vergleichbar sind MIN()und mit MAX()diesen nicht funktionieren:

SELECT key, MIN(value) AS value
FROM tableX
GROUP BY key ;

PostgreSQL verfügt über einen speziellen Nicht-Standard- DISTINCT ONOperator, der ebenfalls verwendet werden kann. Optional können Sie ORDER BYauswählen, welche Zeile aus jeder Gruppe ausgewählt werden soll:

SELECT DISTINCT ON (key) key, value
FROM tableX
-- ORDER BY key, <some_other_expressions> ;
ypercubeᵀᴹ
quelle
2
@WilliamKF Wenn Sie mit "willkürlich ausgewählt" "zufällig ausgewählt" meinen, ersetzen Sie einfach ORDER BY whateverdie Abfrage in ypercube durch einen Aufruf einer Funktion, um die Ergebnisse zufällig zu sortieren.
Leigh Riffel
1
@LeighRiffel Es muss nicht zufällig sein, jede Wahl, so einfach wie die erste, auf die man stößt, funktioniert einwandfrei.
WilliamKF
3

Für MS-SQL Server:

;with FinalDataset as
(
    select *,
        row_number() over(partition by key order by value) as rownum
    from YourOriginalTable
)
select
   key,
   value
from FinalDataset 
where rownum = 1

Ebenso könnten Sie rownum = 2 für Ihre zweite Ergebnismenge haben

JP Chauhan
quelle
2

Ähnlich der akzeptierten Antwort, aber anstelle von min () oder max () können Sie auch array_agg () verwenden.

SELECT key, (array_agg(value))[1] AS value
FROM tableX
GROUP BY key ;

Sie können optional Werte innerhalb des Arrays bestellen, um den größten oder kleinsten Wert auszuwählen:

SELECT key, (array_agg(value) ORDER BY value DESC)[1] AS value
FROM tableX
GROUP BY key ;

(geprüft auf PostgreSQL)

alexkovelsky
quelle