Warum funktioniert SELECT DISTINCT * FROM tabledas bei dir nicht?
Ypercubeᵀᴹ
19
Wenn Ihre Tabelle eine PK hat, sollten alle Zeilen distinctper Definition sein. Wenn Sie versuchen, nur DISTINCT field1alle anderen Spalten auszuwählen, aber irgendwie zurückzugeben, was sollte für die Spalten geschehen, die mehr als einen Wert für einen bestimmten field1Wert haben? Sie müssten beispielsweise eine GROUP BYArt Aggregation für die anderen Spalten verwenden.
Martin Smith
1
Wenn Sie wiederholte Zeilen und nicht nur unterschiedliche Zeilen möchten, entfernen Sie das eindeutige Schlüsselwort.
Hyperboreus
2
Können Sie ein Beispiel geben, wie die Ergebnisse aussehen sollen? Bisher kann ich Ihre gewünschte Anfrage nicht verstehen.
Was gelegentlich mit einer eindeutigen on-Aussage geschrieben werden kann:
selectdistincton field1 *fromtable
Auf den meisten Plattformen funktioniert jedoch keines der oben genannten Verfahren, da das Verhalten in den anderen Spalten nicht angegeben ist. (Das erste funktioniert in MySQL, wenn Sie es verwenden.)
Sie können die verschiedenen Felder abrufen und jedes Mal eine einzelne Zeile auswählen.
Auf einigen Plattformen (z. B. PostgreSQL, Oracle, T-SQL) kann dies direkt mithilfe von Fensterfunktionen erfolgen:
Bei anderen (MySQL, SQLite) müssen Sie Unterabfragen schreiben, mit denen Sie die gesamte Tabelle mit sich selbst verbinden können ( Beispiel ). Dies wird daher nicht empfohlen.
Die Abfrage wird für mich nicht analysiert und gibt einen Fehler aus : The ranking function "row_number" must have an ORDER BY clause. Wir müssen order by-Klausel nach Partition nach field1 hinzufügen. Die richtige Abfrage lautet also select * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
Ankur-m
1
Vielen Dank! Ich war im gleichen Problem und die Lösung war die GROUP BY
Joaquin Iurchuk
2
Auch in Oracle (Oracle SQL Developer) können Sie nicht angeben select *, row_number() over (partition by field1 order by field2) as row_number from table. Sie müssen explizit Tabellenname / Alias in der ausgewählten Abfrage verwendenselect **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
meta4
1
@ Jarlh: Könnte ... heute sein. Wie Sie vielleicht bemerken, ist diese Antwort fast 7 Jahre alt, ein Zeitpunkt, an dem dies nicht der Fall war, soweit ich mich von hinten erinnern kann, als ich aktiv war. Sie können die Antwort gerne erneut markieren und / oder bearbeiten, wenn Sie dies für erforderlich halten.
Denis de Bernardy
2
select distinct on (field1) * from table;; funktioniert auch in PostgreSQL
Chilianu Bogdan
61
Aus der Formulierung Ihrer Frage geht hervor, dass Sie die unterschiedlichen Werte für ein bestimmtes Feld auswählen möchten und für jeden dieser Werte alle anderen Spaltenwerte in derselben Zeile aufgelistet werden sollen. Die meisten DBMS erlauben dies weder mit DISTINCTnoch GROUP BY, da das Ergebnis nicht bestimmt wird.
Stellen Sie sich das so vor: Wenn Ihr field1mehr als einmal vorkommt, wird der Wert von field2aufgelistet (vorausgesetzt, Sie haben den gleichen Wert für field1in zwei Zeilen, aber zwei unterschiedliche Werte für field2in diesen beiden Zeilen).
Sie können jedoch Aggregatfunktionen verwenden (explizit für jedes Feld, das angezeigt werden soll) und GROUP BYstatt DISTINCT:
+1 für diese Lösung. So was wir tun können SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1, und field2, 3, 4 ,,, nicht als ganze Zahlen (oder andere Stellen) erforderlich, können sie Textfelder als auch sein
Stiel
Hat gut funktioniert, bis ich an einer booleschen Säule feststeckte. MIN (Dynamic) -Spaltenwerte werden in false geändert, auch wenn dies der Fall ist. Alle anderen Aggregatfunktionen, die vor 6 Minuten für die Adressierung von boolean - signonsridhar verfügbar waren. Summe (dynamisch) geändert falsch zu 1
signonsridhar
1
Ein großartiger Vorschlag führte mich zu meiner Lösung, die ich für universeller halte - werfen Sie einen Blick darauf!
Garrett Simpson
@signonsridhar wandelt Ihren Booleschen Wert in ein int um und verwendet sum; zBsum(cast(COL as int)) > 0
Drew
26
Wenn ich Ihr Problem richtig verstanden habe, ähnelt es einem, das ich gerade hatte. Sie möchten die Verwendbarkeit von DISTINCT auf ein bestimmtes Feld beschränken können, anstatt es auf alle Daten anzuwenden.
Wenn Sie GROUP BY ohne Aggregatfunktion verwenden, ist jedes Feld, in dem Sie GROUP BY verwenden, Ihre DISTINCT-Datei.
Wenn Sie Ihre Anfrage stellen:
SELECT*fromtableGROUPBY field1;
Es werden alle Ihre Ergebnisse basierend auf einer einzelnen Instanz von Feld1 angezeigt.
Zum Beispiel, wenn Sie eine Tabelle mit Name, Adresse und Stadt haben. Eine einzelne Person hat mehrere Adressen aufgezeichnet, aber Sie möchten nur eine einzige Adresse für die Person, die Sie wie folgt abfragen können:
SELECT*FROM persons GROUPBY name;
Das Ergebnis ist, dass nur eine Instanz dieses Namens mit ihrer Adresse angezeigt wird und die andere in der resultierenden Tabelle weggelassen wird. Achtung: Wenn Ihre Dateien atomare Werte wie Vorname und Nachname haben, die Sie nach beiden gruppieren möchten.
SELECT*FROM persons GROUPBY lastName, firstName;
Wenn zwei Personen denselben Nachnamen haben und Sie nur nach Nachnamen gruppieren, wird eine dieser Personen in den Ergebnissen nicht berücksichtigt. Sie müssen diese Dinge berücksichtigen. Hoffe das hilft.
Warum gibt es, Caliaswenn es ohne es funktionieren kann? in der SchlangeFROM dbo.TABLE AS C
Talha
2
Ich glaube, das liegt an meiner Verwendung von RedGate SQLPrompt. So wie ich es konfiguriert habe, werden immer Aliase hinzugefügt - auch wenn dies nicht erforderlich ist. Es ist da "nur für den Fall"
Stormy
Das sah für mich vielversprechend aus, brachte aber immer noch alle Zeilen zurück, nicht das eindeutige Feld1. :(
Michael Fever
13
Das ist eine wirklich gute Frage. Ich habe hier bereits einige nützliche Antworten gelesen, aber wahrscheinlich kann ich eine genauere Erklärung hinzufügen.
Das Reduzieren der Anzahl der Abfrageergebnisse mit einer GROUP BY-Anweisung ist einfach, solange Sie keine zusätzlichen Informationen abfragen. Nehmen wir an, Sie haben die folgende Tabelle "Standorte".
--country-- --city--
France Lyon
Poland Krakow
France Paris
France Marseille
Italy Milano
Nun die Abfrage
SELECT country FROM locations
GROUPBY country
wird darin enden, dass:
--country--
France
Poland
Italy
Allerdings die folgende Abfrage
SELECT country, city FROM locations
GROUPBY country
... wirft einen Fehler in MS SQL aus, denn wie kann Ihr Computer wissen, welche der drei französischen Städte "Lyon", "Paris" oder "Marseille" Sie im Feld rechts von "Frankreich" lesen möchten?
Um die zweite Abfrage zu korrigieren, müssen Sie diese Informationen hinzufügen. Eine Möglichkeit, dies zu tun, besteht darin, die Funktionen MAX () oder MIN () zu verwenden und den größten oder kleinsten Wert unter allen Kandidaten auszuwählen. MAX () und MIN () gelten nicht nur für numerische Werte, sondern vergleichen auch die alphabetische Reihenfolge der Zeichenfolgenwerte.
SELECT country, MAX(city)FROM locations
GROUPBY country
wird darin enden, dass:
--country-- --city--
France Paris
Poland Krakow
Italy Milano
oder:
SELECT country, MIN(city)FROM locations
GROUPBY country
wird darin enden, dass:
--country-- --city--
France Lyon
Poland Krakow
Italy Milano
Diese Funktionen sind eine gute Lösung, solange Sie Ihren Wert an beiden Enden der alphabetischen (oder numerischen) Reihenfolge auswählen können. Aber was ist, wenn dies nicht der Fall ist? Nehmen wir an, Sie benötigen einen Wert mit einem bestimmten Merkmal, z. B. beginnend mit dem Buchstaben 'M'. Jetzt wird es kompliziert.
Die einzige Lösung, die ich bisher finden konnte, besteht darin, Ihre gesamte Abfrage in eine Unterabfrage zu stellen und die zusätzliche Spalte außerhalb von Hand zu erstellen:
SELECT
countrylist.*,(SELECTTOP1 city
FROM locations
WHERE
country = countrylist.country
AND city like'M%')FROM(SELECT country FROM locations
GROUPBY country) countrylist
wird darin enden, dass:
--country-- --city--
France Marseille
Poland NULL
Italy Milano
Tolle Frage @aryaxt - Sie können sagen, dass es eine großartige Frage war, weil Sie sie vor 5 Jahren gestellt haben und ich heute darauf gestoßen bin, um die Antwort zu finden!
Ich habe nur versucht, die akzeptierte Antwort zu bearbeiten, um dies einzuschließen, aber falls meine Bearbeitung es nicht schafft in:
Wenn Ihre Tabelle nicht so groß wäre und Ihr Primärschlüssel eine automatisch inkrementierende Ganzzahl wäre, könnten Sie Folgendes tun:
SELECTtable.*FROMtable--be able to take out dupes laterLEFTJOIN(SELECT field, MAX(id)as id
FROMtableGROUPBY field
)as noDupes on noDupes.id =table.id
WHERE//this will result in only the last instance being seen
noDupes.id isnotNULL
Für SQL Server können Sie den Funktionen dens_rank und zusätzliche Fensterfunktionen verwenden, um alle Zeilen UND Spalten mit doppelten Werten für bestimmte Spalten abzurufen. Hier ist ein Beispiel...
with t as(select col1 ='a', col2 ='b', col3 ='c', other ='r1'unionallselect col1 ='c', col2 ='b', col3 ='a', other ='r2'unionallselect col1 ='a', col2 ='b', col3 ='c', other ='r3'unionallselect col1 ='a', col2 ='b', col3 ='c', other ='r4'unionallselect col1 ='c', col2 ='b', col3 ='a', other ='r5'unionallselect col1 ='a', col2 ='a', col3 ='a', other ='r6'), tdr as(select*,
total_dr_rows = count(*)over(partitionby dr)from(select*,
dr = dense_rank()over(orderby col1, col2, col3),
dr_rn = row_number()over(partitionby col1, col2, col3 orderby other)from
t
) x
)select*from tdr where total_dr_rows >1
Dies erfordert eine Zeilenanzahl für jede unterschiedliche Kombination von col1, col2 und col3.
Das hat bei mir funktioniert !! Wenn Sie fetch_array () verwenden, müssen Sie jede Zeile über eine Indexbezeichnung aufrufen, anstatt implizit den Zeilennamen aufzurufen. Es gibt nicht genug Zeichen, um das Beispiel aufzuschreiben, das ich habe: X Entschuldigung !!
Wie in der akzeptierten Antwort erwähnt, würde für die meisten Inkarnationen von SQL funktionieren
Garrett Simpson
0
Fand dies an anderer Stelle hier, aber dies ist eine einfache Lösung, die funktioniert:
WITH cte AS/* Declaring a new table named 'cte' to be a clone of your table */(SELECT*, ROW_NUMBER()OVER(PARTITIONBY id ORDERBY val1 DESC)AS rn
FROM MyTable /* Selecting only unique values based on the "id" field */)SELECT*/* Here you can specify several columns to retrieve */FROM cte
WHERE rn =1
Die GROUP BY-Klausel muss mit ausgewählten Feldern übereinstimmen. sonst wird es Fehler wiefiled2 must appear in the GROUP BY clause or be used in an aggregate function
Viuu -a
-2
Fügen Sie einfach alle Ihre Felder in die GROUP BY-Klausel ein.
Das macht den Job nicht. Sie haben die eindeutige Spalte in der Unterabfrage ausgewählt, aber die where-Klausel ruft alle diese Spalten mit diesem Wert ab. Die Abfrage ist also so gut wie das Schreiben von 'select * from table', es sei denn, die Spalte 'field' ist eine eindeutige Spalte. In diesem Fall ist die Unterscheidung in dieser Spalte überhaupt nicht erforderlich.
Ankur-m
-3
SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 funktioniert, wenn die Werte aller drei Spalten in der Tabelle eindeutig sind.
Wenn Sie beispielsweise mehrere identische Werte für den Vornamen haben, der Nachname und andere Informationen in den ausgewählten Spalten jedoch unterschiedlich sind, wird der Datensatz in die Ergebnismenge aufgenommen.
Dies beantwortet nicht die Frage, das OP hat versucht, alle Daten der Tabelle abzurufen, aber Zeilen mit Duplikaten eines einzelnen Feldes zu entfernen
SELECT DISTINCT * FROM table
das bei dir nicht?distinct
per Definition sein. Wenn Sie versuchen, nurDISTINCT field1
alle anderen Spalten auszuwählen, aber irgendwie zurückzugeben, was sollte für die Spalten geschehen, die mehr als einen Wert für einen bestimmtenfield1
Wert haben? Sie müssten beispielsweise eineGROUP BY
Art Aggregation für die anderen Spalten verwenden.Antworten:
Sie suchen eine Gruppe von:
Was gelegentlich mit einer eindeutigen on-Aussage geschrieben werden kann:
Auf den meisten Plattformen funktioniert jedoch keines der oben genannten Verfahren, da das Verhalten in den anderen Spalten nicht angegeben ist. (Das erste funktioniert in MySQL, wenn Sie es verwenden.)
Sie können die verschiedenen Felder abrufen und jedes Mal eine einzelne Zeile auswählen.
Auf einigen Plattformen (z. B. PostgreSQL, Oracle, T-SQL) kann dies direkt mithilfe von Fensterfunktionen erfolgen:
Bei anderen (MySQL, SQLite) müssen Sie Unterabfragen schreiben, mit denen Sie die gesamte Tabelle mit sich selbst verbinden können ( Beispiel ). Dies wird daher nicht empfohlen.
quelle
The ranking function "row_number" must have an ORDER BY clause
. Wir müssen order by-Klausel nach Partition nach field1 hinzufügen. Die richtige Abfrage lautet alsoselect * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
GROUP BY
select *, row_number() over (partition by field1 order by field2) as row_number from table
. Sie müssen explizit Tabellenname / Alias in der ausgewählten Abfrage verwendenselect **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
select distinct on (field1) * from table
;; funktioniert auch in PostgreSQLAus der Formulierung Ihrer Frage geht hervor, dass Sie die unterschiedlichen Werte für ein bestimmtes Feld auswählen möchten und für jeden dieser Werte alle anderen Spaltenwerte in derselben Zeile aufgelistet werden sollen. Die meisten DBMS erlauben dies weder mit
DISTINCT
nochGROUP BY
, da das Ergebnis nicht bestimmt wird.Stellen Sie sich das so vor: Wenn Ihr
field1
mehr als einmal vorkommt, wird der Wert vonfield2
aufgelistet (vorausgesetzt, Sie haben den gleichen Wert fürfield1
in zwei Zeilen, aber zwei unterschiedliche Werte fürfield2
in diesen beiden Zeilen).Sie können jedoch Aggregatfunktionen verwenden (explizit für jedes Feld, das angezeigt werden soll) und
GROUP BY
stattDISTINCT
:quelle
SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1
, und field2, 3, 4 ,,, nicht als ganze Zahlen (oder andere Stellen) erforderlich, können sie Textfelder als auch seinsum(cast(COL as int)) > 0
Wenn ich Ihr Problem richtig verstanden habe, ähnelt es einem, das ich gerade hatte. Sie möchten die Verwendbarkeit von DISTINCT auf ein bestimmtes Feld beschränken können, anstatt es auf alle Daten anzuwenden.
Wenn Sie GROUP BY ohne Aggregatfunktion verwenden, ist jedes Feld, in dem Sie GROUP BY verwenden, Ihre DISTINCT-Datei.
Wenn Sie Ihre Anfrage stellen:
Es werden alle Ihre Ergebnisse basierend auf einer einzelnen Instanz von Feld1 angezeigt.
Zum Beispiel, wenn Sie eine Tabelle mit Name, Adresse und Stadt haben. Eine einzelne Person hat mehrere Adressen aufgezeichnet, aber Sie möchten nur eine einzige Adresse für die Person, die Sie wie folgt abfragen können:
Das Ergebnis ist, dass nur eine Instanz dieses Namens mit ihrer Adresse angezeigt wird und die andere in der resultierenden Tabelle weggelassen wird. Achtung: Wenn Ihre Dateien atomare Werte wie Vorname und Nachname haben, die Sie nach beiden gruppieren möchten.
Wenn zwei Personen denselben Nachnamen haben und Sie nur nach Nachnamen gruppieren, wird eine dieser Personen in den Ergebnissen nicht berücksichtigt. Sie müssen diese Dinge berücksichtigen. Hoffe das hilft.
quelle
quelle
C
alias
wenn es ohne es funktionieren kann? in der SchlangeFROM dbo.TABLE AS C
Das ist eine wirklich gute Frage. Ich habe hier bereits einige nützliche Antworten gelesen, aber wahrscheinlich kann ich eine genauere Erklärung hinzufügen.
Das Reduzieren der Anzahl der Abfrageergebnisse mit einer GROUP BY-Anweisung ist einfach, solange Sie keine zusätzlichen Informationen abfragen. Nehmen wir an, Sie haben die folgende Tabelle "Standorte".
Nun die Abfrage
wird darin enden, dass:
Allerdings die folgende Abfrage
... wirft einen Fehler in MS SQL aus, denn wie kann Ihr Computer wissen, welche der drei französischen Städte "Lyon", "Paris" oder "Marseille" Sie im Feld rechts von "Frankreich" lesen möchten?
Um die zweite Abfrage zu korrigieren, müssen Sie diese Informationen hinzufügen. Eine Möglichkeit, dies zu tun, besteht darin, die Funktionen MAX () oder MIN () zu verwenden und den größten oder kleinsten Wert unter allen Kandidaten auszuwählen. MAX () und MIN () gelten nicht nur für numerische Werte, sondern vergleichen auch die alphabetische Reihenfolge der Zeichenfolgenwerte.
wird darin enden, dass:
oder:
wird darin enden, dass:
Diese Funktionen sind eine gute Lösung, solange Sie Ihren Wert an beiden Enden der alphabetischen (oder numerischen) Reihenfolge auswählen können. Aber was ist, wenn dies nicht der Fall ist? Nehmen wir an, Sie benötigen einen Wert mit einem bestimmten Merkmal, z. B. beginnend mit dem Buchstaben 'M'. Jetzt wird es kompliziert.
Die einzige Lösung, die ich bisher finden konnte, besteht darin, Ihre gesamte Abfrage in eine Unterabfrage zu stellen und die zusätzliche Spalte außerhalb von Hand zu erstellen:
wird darin enden, dass:
quelle
Tolle Frage @aryaxt - Sie können sagen, dass es eine großartige Frage war, weil Sie sie vor 5 Jahren gestellt haben und ich heute darauf gestoßen bin, um die Antwort zu finden!
Ich habe nur versucht, die akzeptierte Antwort zu bearbeiten, um dies einzuschließen, aber falls meine Bearbeitung es nicht schafft in:
Wenn Ihre Tabelle nicht so groß wäre und Ihr Primärschlüssel eine automatisch inkrementierende Ganzzahl wäre, könnten Sie Folgendes tun:
quelle
Versuchen
quelle
Sie können dies mit einer
WITH
Klausel tun .Zum Beispiel:
Auf diese Weise können Sie auch nur die in der
WITH
Klauselabfrage ausgewählten Zeilen auswählen .quelle
Für SQL Server können Sie den Funktionen dens_rank und zusätzliche Fensterfunktionen verwenden, um alle Zeilen UND Spalten mit doppelten Werten für bestimmte Spalten abzurufen. Hier ist ein Beispiel...
Dies erfordert eine Zeilenanzahl für jede unterschiedliche Kombination von col1, col2 und col3.
quelle
quelle
In diesem
ORDER BY
Beispiel habe ich gerade ein ID-Feld hinzugefügtquelle
Fand dies an anderer Stelle hier, aber dies ist eine einfache Lösung, die funktioniert:
quelle
Fügen Sie GROUP BY zu dem Feld hinzu, in dem Sie nach Duplikaten suchen möchten, nach denen Ihre Abfrage möglicherweise aussieht
Feld1 wird aktiviert, um doppelte Datensätze auszuschließen
oder Sie können wie abfragen
Doppelte Datensätze von Feld1 werden von SELECT ausgeschlossen
quelle
filed2 must appear in the GROUP BY clause or be used in an aggregate function
Fügen Sie einfach alle Ihre Felder in die GROUP BY-Klausel ein.
quelle
Dies kann durch innere Abfrage erfolgen
quelle
quelle
SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 funktioniert, wenn die Werte aller drei Spalten in der Tabelle eindeutig sind.
Wenn Sie beispielsweise mehrere identische Werte für den Vornamen haben, der Nachname und andere Informationen in den ausgewählten Spalten jedoch unterschiedlich sind, wird der Datensatz in die Ergebnismenge aufgenommen.
quelle
Ich würde vorschlagen, zu verwenden
Auf diese Weise werden alle Datensätze zurückgegeben, wenn Sie in mehreren Zeilen denselben Wert in Feld1 haben.
quelle
SELECT * FROM table;
. Noch mehr Es ist langsam.