it-swarm.com.de

SQL / mysql - Wählen Sie distinct / UNIQUE aus, aber geben Sie alle Spalten zurück?

SELECT DISTINCT field1, field2, field3, ......   FROM table

Ich versuche die folgende SQL-Anweisung auszuführen, möchte aber, dass alle Spalten zurückgegeben werden. Ist dies möglich? So etwas wie:

SELECT DISTINCT field1, * from table
337
aryaxt

Sie suchen eine Gruppe von:

select *
from table
group by field1

Was gelegentlich mit einer eindeutigen on-Anweisung geschrieben werden kann:

select distinct on field1 *
from table

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 sich jedes Mal an die Auswahl einer beliebigen Zeile halten.

Auf einigen Plattformen (z. B. PostgreSQL, Oracle, T-SQL) kann dies direkt mithilfe von Fensterfunktionen erfolgen:

select *
from (
   select *,
          row_number() over (partition by field1 order by field2) as row_number
   from table
   ) as rows
where row_number = 1

Bei anderen (MySQL, SQLite) müssen Sie Unterabfragen schreiben, mit denen Sie die gesamte Tabelle mit sich selbst verknüpfen können ( Beispiel ). Dies wird daher nicht empfohlen.

373

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 haben möchten. Die meisten DBMS erlauben dies weder mit DISTINCT noch mit GROUP BY, da das Ergebnis nicht bestimmt wird.

Stellen Sie sich das so vor: Wenn Ihr field1 mehrmals vorkommt, wird der Wert von field2 aufgelistet (vorausgesetzt, Sie haben denselben Wert für field1 in zwei Zeilen, aber zwei unterschiedlichen Werten von field2 in diesen beiden Zeilen).

Sie können jedoch Aggregatfunktionen verwenden (explizit für jedes Feld, das angezeigt werden soll) und einen GROUP BY anstelle von DISTINCT verwenden:

SELECT field1, MAX(field2), COUNT(field3), SUM(field4), .... FROM table GROUP BY field1
55
Costi Ciudatu

Wenn ich Ihr Problem richtig verstanden habe, ähnelt es dem, das ich gerade hatte. Sie möchten die Verwendbarkeit von DISTINCT auf ein bestimmtes Feld beschränken, anstatt es auf alle Daten anzuwenden.

Wenn Sie GROUP BY ohne Aggregatfunktion verwenden, wird das von Ihnen GROUP BY-Feld als DISTINCT-Feld abgelegt.

Wenn Sie Ihre Frage stellen:

SELECT * from table GROUP BY field1;

Es werden alle Ihre Ergebnisse basierend auf einer einzelnen Instanz von field1 angezeigt.

Zum Beispiel, wenn Sie eine Tabelle mit Name, Adresse und Stadt haben. Bei einer einzelnen Person sind mehrere Adressen gespeichert. Wenn Sie jedoch nur eine einzelne Adresse für die Person möchten, können Sie Folgendes abfragen:

SELECT * FROM persons GROUP BY name;

Das Ergebnis wird sein, dass nur eine Instanz dieses Namens mit seiner Adresse erscheint und die andere in der resultierenden Tabelle weggelassen wird. Achtung: Wenn Ihre Dateien atomare Werte wie Vorname und Nachname haben, möchten Sie beide gruppieren.

SELECT * FROM persons GROUP BY lastName, firstName;

wenn zwei Personen denselben Nachnamen haben und Sie nur nach dem Nachnamen gruppieren, wird eine dieser Personen aus den Ergebnissen ausgeschlossen. Sie müssen diese Dinge berücksichtigen. Hoffe das hilft.

20
rocklandcitizen
SELECT  c2.field1 ,
        field2
FROM    (SELECT DISTINCT
                field1
         FROM   dbo.TABLE AS C
        ) AS c1
        JOIN dbo.TABLE AS c2 ON c1.field1 = c2.field1
13
Stormy

Das ist eine wirklich gute Frage. Ich habe hier bereits einige nützliche Antworten gelesen, kann aber wahrscheinlich 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. Angenommen, 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
GROUP BY country

wird darin enden, dass:

--country--
 France
 Poland
 Italy

Jedoch die folgende Abfrage

SELECT country, city FROM locations
GROUP BY country

... in MS SQL einen Fehler auslöst, denn woher weiß Ihr Computer, 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
GROUP BY country

wird darin enden, dass:

--country-- --city--
 France      Paris
 Poland      Krakow
 Italy       Milano

oder:

SELECT country, MIN(city) FROM locations
GROUP BY 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 den Enden der alphabetischen (oder numerischen) Reihenfolge auswählen können. Aber was ist, wenn dies nicht der Fall ist? Angenommen, Sie benötigen einen Wert mit einem bestimmten Merkmal, z. 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 einzufügen und die zusätzliche Spalte außerhalb der Abfrage manuell zu erstellen:

SELECT
     countrylist.*,
     (SELECT TOP 1 city
     FROM locations
     WHERE
          country = countrylist.country
          AND city like 'M%'
     )
FROM
(SELECT country FROM locations
GROUP BY country) countrylist

wird darin enden, dass:

--country-- --city--
 France      Marseille
 Poland      NULL
 Italy       Milano
7
Ulf Sanne

Großartige 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 gerade versucht, die akzeptierte Antwort so zu bearbeiten, dass sie diese enthält. Falls meine Bearbeitung dies nicht schafft:

Wenn Ihre Tabelle nicht so groß wäre und Ihr Primärschlüssel eine automatisch inkrementierende Ganzzahl wäre, könnten Sie Folgendes tun:

SELECT 
  table.*
FROM table
--be able to take out dupes later
LEFT JOIN (
  SELECT field, MAX(id) as id
  FROM table
  GROUP BY field
) as noDupes on noDupes.id = table.id
WHERE
  //this will result in only the last instance being seen
  noDupes.id is not NULL
3
Garrett Simpson

Sie können dies mit einer WITH -Klausel tun.

Zum Beispiel:

WITH c AS (SELECT DISTINCT a, b, c FROM tableName)
SELECT * FROM tableName r, c WHERE c.rowid=r.rowid AND c.a=r.a AND c.b=r.b AND c.c=r.c

Auf diese Weise können Sie auch nur die Zeilen auswählen, die in der Abfrage "WITH" ausgewählt wurden.

2
user2225399

Für SQL Server können Sie den dichten_Rang und zusätzliche Fensterfunktionen verwenden, um alle Zeilen UND Spalten mit doppelten Werten für die angegebenen Spalten abzurufen. Hier ist ein Beispiel...

with t as (
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r1' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r2' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r3' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r4' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r5' union all
    select col1 = 'a', col2 = 'a', col3 = 'a', other = 'r6'
), tdr as (
    select 
        *, 
        total_dr_rows = count(*) over(partition by dr)
    from (
        select 
            *, 
            dr = dense_rank() over(order by col1, col2, col3),
            dr_rn = row_number() over(partition by col1, col2, col3 order by other)
        from 
            t
    ) x
)

select * from tdr where total_dr_rows > 1

Hierbei wird für jede eindeutige Kombination von Spalte 1, Spalte 2 und Spalte 3 eine Zeilenzählung durchgeführt.

1
dotjoe

Versuchen

SELECT table.* FROM table 
WHERE otherField = 'otherValue'
GROUP BY table.fieldWantedToBeDistinct
limit x
1
Pedro Ramos
SELECT *
FROM tblname
GROUP BY duplicate_values
ORDER BY ex.VISITED_ON DESC
LIMIT 0 , 30

in ORDER BY habe ich gerade ein Beispiel angegeben, hier können Sie auch ein ID-Feld hinzufügen

0
SagarPPanchal