Ich muss alle Zeilen aus einer Tabelle abrufen, in der zwei Spalten zusammen unterschiedlich sind. Ich möchte also alle Verkäufe, die keine anderen Verkäufe haben, die am selben Tag zum gleichen Preis getätigt wurden. Die Verkäufe, die basierend auf Tag und Preis eindeutig sind, werden auf einen aktiven Status aktualisiert.
Also denke ich:
UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
FROM sales
HAVING count = 1)
Aber mein Gehirn tut weh, wenn ich noch weiter gehe.
sql
postgresql
sql-update
duplicates
distinct
sheats
quelle
quelle
Wenn Sie die bisherigen Antworten zusammenstellen, aufräumen und verbessern, gelangen Sie zu dieser überlegenen Frage:
Welches ist viel schneller als beide. Nukes die Leistung der aktuell akzeptierten Antwort um den Faktor 10 - 15 (in meinen Tests auf PostgreSQL 8.4 und 9.1).
Dies ist jedoch noch lange nicht optimal. Verwenden Sie einen
NOT EXISTS
(Anti-) Semi-Join für eine noch bessere Leistung.EXISTS
ist Standard-SQL, gibt es schon immer (zumindest seit PostgreSQL 7.2, lange bevor diese Frage gestellt wurde) und passt perfekt zu den vorgestellten Anforderungen:db <> hier fummeln
Alte SQL-Geige
Eindeutiger Schlüssel zur Identifizierung der Zeile
Wenn Sie (
id
im Beispiel) keinen Primär- oder eindeutigen Schlüssel für die Tabelle haben , können Siectid
den Zweck dieser Abfrage durch die Systemspalte ersetzen (jedoch nicht für andere Zwecke):Jede Tabelle sollte einen Primärschlüssel haben. Fügen Sie eine hinzu, wenn Sie noch keine hatten. Ich schlage ein
serial
oder ein vorIDENTITY
Spalte in Postgres 10+ vor.Verbunden:
Wie geht das schneller?
Die Unterabfrage im
EXISTS
Anti-Semi-Join kann die Auswertung beenden, sobald der erste Betrüger gefunden wird (es macht keinen Sinn, weiter zu suchen). Für eine Basistabelle mit wenigen Duplikaten ist dies nur geringfügig effizienter. Mit vielen Duplikaten wird diese Art und Weise effizienter zu gestalten .Leere Updates ausschließen
Für Zeilen, die
status = 'ACTIVE'
dieses Update bereits haben, würde sich nichts ändern, aber dennoch eine neue Zeilenversion zum vollen Preis einfügen (kleinere Ausnahmen gelten). Normalerweise willst du das nicht. Fügen Sie eine weitereWHERE
Bedingung wie oben gezeigt hinzu, um dies zu vermeiden und noch schneller zu machen:Wenn
status
definiert istNOT NULL
, können Sie vereinfachen, um:Subtiler Unterschied in der NULL-Behandlung
Diese Abfrage behandelt (im Gegensatz zu der derzeit von Joel akzeptierten Antwort ) NULL-Werte nicht als gleich. Die folgenden zwei Zeilen für
(saleprice, saledate)
würden als "verschieden" qualifiziert (obwohl sie mit dem menschlichen Auge identisch aussehen):Übergibt auch einen eindeutigen Index und fast überall sonst, da NULL-Werte gemäß dem SQL-Standard nicht gleich sind. Sehen:
OTOH,
GROUP BY
,DISTINCT
oderDISTINCT ON ()
treat NULL - Werte als gleich. Verwenden Sie einen geeigneten Abfragestil, je nachdem, was Sie erreichen möchten. Sie können diese schnellere Abfrage weiterhin mitIS NOT DISTINCT FROM
anstelle von=
für einen oder alle Vergleiche verwenden, um den NULL-Vergleich gleich zu machen. Mehr:Wenn alle verglichenen Spalten definiert sind
NOT NULL
, gibt es keinen Raum für Meinungsverschiedenheiten.quelle
count(*)
ist mehr effizienter alscount(<expression>)
. Probier es einfach. Postgres hat eine schnellere Implementierung für diese Variante der Aggregatfunktion. Vielleicht verwechseln Sie Postgres mit einem anderen RDBMS?Das Problem bei Ihrer Abfrage besteht darin, dass Sie bei Verwendung einer GROUP BY-Klausel (die Sie im Wesentlichen mit einer eindeutigen Klausel ausführen) nur Spalten verwenden können, nach denen Sie Funktionen gruppieren oder aggregieren. Sie können die Spalten-ID nicht verwenden, da möglicherweise unterschiedliche Werte vorhanden sind. In Ihrem Fall gibt es aufgrund der HAVING-Klausel immer nur einen Wert, aber die meisten RDBMS sind nicht intelligent genug, um dies zu erkennen.
Dies sollte jedoch funktionieren (und benötigt keinen Join):
Sie können auch MAX oder AVG anstelle von MIN verwenden. Es ist nur wichtig, eine Funktion zu verwenden, die den Wert der Spalte zurückgibt, wenn nur eine übereinstimmende Zeile vorhanden ist.
quelle
Ich möchte die unterschiedlichen Werte aus einer Spalte 'GrondOfLucht' auswählen, aber sie sollten in der Reihenfolge sortiert werden, die in der Spalte 'Sortieren' angegeben ist. Ich kann nicht die eindeutigen Werte nur einer Spalte verwenden
Außerdem wird die Spalte "Sortieren" angezeigt. Da "GrondOfLucht" UND "Sortieren" nicht eindeutig ist, werden ALLE Zeilen ausgegeben.
Verwenden Sie die GRUPPE, um die Datensätze von 'GrondOfLucht' in der durch 'Sortieren angegebenen Reihenfolge' auszuwählen
quelle
Wenn Ihr DBMS die Unterscheidung mit mehreren Spalten wie folgt nicht unterstützt:
Mehrfachauswahl kann im Allgemeinen wie folgt sicher ausgeführt werden:
Da dies auf den meisten DBMS funktionieren kann und dies voraussichtlich schneller als die Gruppierung nach Lösung ist, vermeiden Sie die Gruppierungsfunktionalität.
quelle