Gibt es eine bessere Möglichkeit, eine Abfrage wie diese durchzuführen:
SELECT COUNT(*)
FROM (SELECT DISTINCT DocumentId, DocumentSessionId
FROM DocumentOutputItems) AS internalQuery
Ich muss die Anzahl der verschiedenen Elemente aus dieser Tabelle zählen, aber das Unterschied ist über zwei Spalten.
Meine Abfrage funktioniert einwandfrei, aber ich habe mich gefragt, ob ich mit nur einer Abfrage (ohne Verwendung einer Unterabfrage) das Endergebnis erzielen kann.
sql
sql-server
performance
tsql
query-optimization
Novitzky
quelle
quelle
Antworten:
Wenn Sie versuchen, die Leistung zu verbessern, können Sie versuchen, eine persistierte berechnete Spalte entweder mit einem Hash oder einem verketteten Wert der beiden Spalten zu erstellen.
Sobald es beibehalten wird, kann die Spalte indiziert und / oder Statistiken erstellt werden, sofern die Spalte deterministisch ist und Sie "gesunde" Datenbankeinstellungen verwenden.
Ich glaube, eine eindeutige Anzahl der berechneten Spalten würde Ihrer Abfrage entsprechen.
quelle
Bearbeiten: Geändert von der weniger zuverlässigen Nur-Prüfsummen-Abfrage habe ich einen Weg gefunden, dies zu tun (in SQL Server 2005), der für mich ziemlich gut funktioniert, und ich kann so viele Spalten verwenden, wie ich brauche (indem ich sie hinzufüge) die CHECKSUM () Funktion). Die REVERSE () -Funktion wandelt die Ints in Varchars um, um die Unterscheidung zuverlässiger zu machen
quelle
Was gefällt Ihnen an Ihrer vorhandenen Abfrage nicht? Wenn Sie befürchten, dass
DISTINCT
über zwei Spalten nicht nur die eindeutigen Permutationen zurückgegeben werden, probieren Sie es aus.Es funktioniert auf jeden Fall so, wie Sie es von Oracle erwarten.
bearbeiten
Ich ging mit Analytik eine Sackgasse entlang, aber die Antwort war bedrückend offensichtlich ...
bearbeiten 2
Angesichts der folgenden Daten wird die oben bereitgestellte Verkettungslösung falsch gezählt:
Also müssen wir ein Trennzeichen einfügen ...
Offensichtlich muss das gewählte Trennzeichen ein Zeichen oder eine Reihe von Zeichen sein, die in keiner der Spalten erscheinen dürfen.
quelle
Um als einzelne Abfrage ausgeführt zu werden, verketten Sie die Spalten und ermitteln Sie dann die eindeutige Anzahl der Instanzen der verketteten Zeichenfolge.
In MySQL können Sie dasselbe ohne den Verkettungsschritt wie folgt tun:
Diese Funktion wird in der MySQL-Dokumentation erwähnt:
http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count-distinct
quelle
SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
Wie wäre es mit so etwas wie:
Wahrscheinlich macht es genau das Gleiche wie Sie es bereits sind, aber es vermeidet das UNTERSCHEIDEN.
quelle
GROUP BY
Problems einige zusätzliche Herausforderungen für die Abfragetransformation mit sich bringen, um die gewünschte Ausgabe zu erzielen (z. B. wenn die ursprüngliche Abfrage bereits vorhanden warGROUP BY
oderHAVING
Klauseln ...)Hier ist eine kürzere Version ohne die Unterauswahl:
Es funktioniert gut in MySQL, und ich denke, dass es dem Optimierer leichter fällt, dieses zu verstehen.
Edit: Anscheinend habe ich MSSQL und MySQL falsch verstanden - sorry, aber vielleicht hilft es trotzdem.
quelle
count ( distinct CHECKSUM ([Field1], [Field2])
Viele (die meisten?) SQL-Datenbanken können mit Tupeln wie Werten arbeiten, sodass Sie einfach
SELECT COUNT(DISTINCT (DocumentId, DocumentSessionId)) FROM DocumentOutputItems;
Folgendes tun können: Wenn Ihre Datenbank dies nicht unterstützt, kann dies gemäß dem Vorschlag von @ oncel-umut-turer von CHECKSUM oder einer anderen Skalarfunktion simuliert werden, die eine gute Eindeutigkeit bietet zBCOUNT(DISTINCT CONCAT(DocumentId, ':', DocumentSessionId))
.Eine verwandte Verwendung von Tupeln ist das Ausführen von
IN
Abfragen wie:SELECT * FROM DocumentOutputItems WHERE (DocumentId, DocumentSessionId) in (('a', '1'), ('b', '2'));
quelle
select count(distinct(a, b))
? : DAn Ihrer Abfrage ist nichts auszusetzen, aber Sie können dies auch folgendermaßen tun:
quelle
Hoffe das funktioniert ich schreibe auf prima vista
quelle
Ich habe diesen Ansatz verwendet und es hat bei mir funktioniert.
Für meinen Fall liefert es das richtige Ergebnis.
quelle
Wenn Sie nur ein Feld für "DISTINCT" hätten, könnten Sie Folgendes verwenden:
und das gibt den gleichen Abfrageplan wie das Original zurück, wie mit SET SHOWPLAN_ALL ON getestet. Sie verwenden jedoch zwei Felder, um etwas Verrücktes auszuprobieren:
Sie haben jedoch Probleme, wenn NULL-Werte beteiligt sind. Ich würde mich einfach an die ursprüngliche Abfrage halten.
quelle
Ich habe dies gefunden, als ich nach meinem eigenen Problem gegoogelt habe und festgestellt habe, dass beim Zählen von DISTINCT-Objekten die richtige Nummer zurückgegeben wird (ich verwende MySQL).
quelle
DocumentId
undDocumentSessionId
). Alexander Kjäll hat bereits die richtige Antwort gepostet, wenn das OP MySQL und nicht MS SQL Server verwendet.Ich wünschte, MS SQL könnte auch so etwas wie COUNT (DISTINCT A, B) tun. Aber es kann nicht.
Zuerst schien mir JayTees Antwort eine Lösung zu sein, aber nach einigen Tests konnte CHECKSUM () keine eindeutigen Werte erstellen. Ein kurzes Beispiel ist, dass sowohl CHECKSUM (31.467.519) als auch CHECKSUM (69.1120.823) dieselbe Antwort geben, nämlich 55.
Dann habe ich einige Nachforschungen angestellt und festgestellt, dass Microsoft die Verwendung von CHECKSUM NICHT zur Änderungserkennung empfiehlt. In einigen Foren schlugen einige die Verwendung vor
das ist aber auch nicht tröstlich.
Sie können die Funktion HASHBYTES () verwenden, wie im TSQL CHECKSUM-Rätsel vorgeschlagen . Dies hat jedoch auch eine geringe Wahrscheinlichkeit, dass keine eindeutigen Ergebnisse zurückgegeben werden.
Ich würde vorschlagen, zu verwenden
quelle
Wie wäre es damit,
Dadurch erhalten wir die Anzahl aller möglichen Kombinationen von DocumentId und DocumentSessionId
quelle
Für mich geht das. Im Orakel:
In jpql:
quelle
Ich hatte eine ähnliche Frage, aber die Abfrage, die ich hatte, war eine Unterabfrage mit den Vergleichsdaten in der Hauptabfrage. etwas wie:
Als ich die Komplexität ignorierte, stellte ich fest, dass ich den Wert von a.code mit der in der ursprünglichen Frage beschriebenen doppelten Unterabfrage nicht in die Unterabfrage aufnehmen konnte
Also fand ich schließlich heraus, dass ich schummeln und die Spalten kombinieren konnte:
Das hat letztendlich funktioniert
quelle
Wenn Sie mit Datentypen fester Länge arbeiten, können
binary
Sie dies sehr einfach und sehr schnell tun. AngenommenDocumentId
undDocumentSessionId
sind beideint
s und sind daher 4 Bytes lang ...Mein spezifisches Problem erforderte, dass ich a
SUM
durch dieCOUNT
unterschiedliche Kombination verschiedener Fremdschlüssel und eines Datumsfelds dividierte, nach einem anderen Fremdschlüssel gruppierte und gelegentlich nach bestimmten Werten oder Schlüsseln filterte. Die Tabelle ist sehr groß, und die Verwendung einer Unterabfrage hat die Abfragezeit erheblich verlängert. Und aufgrund der Komplexität waren Statistiken einfach keine praktikable Option. DasCHECKSUM
Konvertierung der Lösung war auch viel zu langsam, insbesondere aufgrund der verschiedenen Datentypen, und ich konnte ihre Unzuverlässigkeit nicht riskieren.Die Verwendung der oben genannten Lösung hatte jedoch praktisch keine Verlängerung der Abfragezeit (im Vergleich zur Verwendung der einfachen Lösung
SUM
) und sollte absolut zuverlässig sein! Es sollte in der Lage sein, anderen in einer ähnlichen Situation zu helfen, also poste ich es hier.quelle
Sie können die Zählfunktion einfach zweimal verwenden.
In diesem Fall wäre es:
quelle
Dieser Code verwendet unterschiedliche Parameter für 2 und gibt die Anzahl der Zeilen an, die für diese unterschiedlichen Werte spezifisch sind. Es hat für mich in MySQL wie ein Zauber funktioniert.
quelle