Pradeep Adigas erster Vorschlag ORDER BY NEWID()
ist in Ordnung und etwas, das ich in der Vergangenheit aus diesem Grund verwendet habe.
Seien Sie vorsichtig bei der Verwendung von RAND()
- In vielen Kontexten wird es nur einmal pro Anweisung ausgeführt, so ORDER BY RAND()
dass es keine Auswirkungen hat (da Sie für jede Zeile dasselbe Ergebnis aus RAND () erhalten).
Zum Beispiel:
SELECT display_name, RAND() FROM tr_person
gibt jeden Namen aus unserer Personentabelle und eine "Zufalls" -Zahl zurück, die für jede Zeile gleich ist. Die Anzahl variiert bei jeder Ausführung der Abfrage, ist jedoch für jede Zeile gleich.
Um zu zeigen, dass dies RAND()
auch in einer ORDER BY
Klausel der Fall ist, versuche ich:
SELECT display_name FROM tr_person ORDER BY RAND(), display_name
Die Ergebnisse werden weiterhin nach dem Namen sortiert, was darauf hinweist, dass das frühere Sortierfeld (das voraussichtlich zufällig ist) keine Auswirkung hat und daher vermutlich immer denselben Wert hat.
Die Sortierung nach NEWID()
funktioniert jedoch, da, wenn NEWID () nicht immer neu bewertet wurde, der Zweck von UUIDs beim Einfügen vieler neuer Zeilen in eine Anweisung mit eindeutigen Bezeichnern als Schlüssel nicht funktioniert.
SELECT display_name FROM tr_person ORDER BY NEWID()
ordnet die Namen "zufällig".
Andere DBMS
Das obige gilt für MSSQL (mindestens 2005 und 2008, und wenn ich mich recht erinnere auch 2000). Eine Funktion, die eine neue UUID zurückgibt, sollte jedes Mal ausgewertet werden, wenn sich in allen DBMS NEWID () unter MSSQL befindet. Es lohnt sich jedoch, dies in der Dokumentation und / oder durch Ihre eigenen Tests zu überprüfen. Es ist wahrscheinlicher, dass das Verhalten anderer Funktionen mit beliebigen Ergebnissen wie RAND () zwischen DBMS variiert. Überprüfen Sie daher erneut die Dokumentation.
Außerdem habe ich gesehen, dass die Sortierung nach UUID-Werten in einigen Kontexten ignoriert wird, da die Datenbank davon ausgeht, dass der Typ keine aussagekräftige Sortierung aufweist. Wenn dies der Fall ist, wandeln Sie die UUID explizit in einen Zeichenfolgentyp in der ordering-Klausel um, oder schließen Sie eine andere Funktion wie CHECKSUM()
in SQL Server ein (möglicherweise besteht auch hier ein geringer Leistungsunterschied, da die Bestellung am ausgeführt wird 32-Bit-Werte, keine 128-Bit-Werte, aber ob der Nutzen davon die Betriebskosten CHECKSUM()
pro Wert überwiegt, überlasse ich Ihnen zu testen.
Randnotiz
Wenn Sie eine willkürliche, aber etwas wiederholbare Reihenfolge wünschen, ordnen Sie die Daten in den Zeilen selbst nach einer relativ unkontrollierten Teilmenge. Entweder oder diese geben die Namen in einer willkürlichen, aber wiederholbaren Reihenfolge zurück:
SELECT display_name FROM tr_person ORDER BY CHECKSUM(display_name), display_name -- order by the checksum of some of the row's data
SELECT display_name FROM tr_person ORDER BY SUBSTRING(display_name, LEN(display_name)/2, 128) -- order by part of the name field, but not in any an obviously recognisable order)
Beliebige, aber wiederholbare Anordnungen sind in Anwendungen nicht oft nützlich. Sie können jedoch beim Testen hilfreich sein, wenn Sie einen Code auf Ergebnisse in einer Vielzahl von Anordnungen testen möchten, aber jeden Durchlauf mehrmals auf die gleiche Weise wiederholen möchten (um das durchschnittliche Timing zu erhalten) Ergebnisse über mehrere Läufe oder das Testen, dass Sie den Code korrigiert haben, behebt ein Problem oder eine Ineffizienz, die zuvor von einer bestimmten Eingabe-Ergebnismenge hervorgehoben wurden, oder dient nur zum Testen, dass Ihr Code "stabil" ist und jedes Mal dasselbe Ergebnis zurückgibt wenn die gleichen Daten in einer bestimmten Reihenfolge gesendet).
Dieser Trick kann auch verwendet werden, um willkürlichere Ergebnisse von Funktionen zu erhalten, die keine nicht deterministischen Aufrufe wie NEWID () in ihrem Körper zulassen. Auch dies ist wahrscheinlich nicht sehr nützlich in der realen Welt, kann sich aber als nützlich erweisen, wenn Sie möchten, dass eine Funktion etwas Zufälliges zurückgibt und "random-ish" gut genug ist (achten Sie jedoch darauf, die Regeln zu beachten, die dies bestimmen wenn benutzerdefinierte Funktionen ausgewertet werden, dh normalerweise nur einmal pro Zeile, oder Ihre Ergebnisse möglicherweise nicht den Erwartungen / Anforderungen entsprechen.
Performance
Wie EBarr hervorhebt, kann es bei den oben genannten Problemen zu Leistungsproblemen kommen. Bei mehr als ein paar Zeilen ist es fast garantiert, dass die Ausgabe auf Tempdb gespoolt wird, bevor die angeforderte Anzahl von Zeilen in der richtigen Reihenfolge zurückgelesen wird. Dies bedeutet, dass Sie möglicherweise einen vollständigen Index finden, selbst wenn Sie nach den Top 10 suchen scan (oder schlimmer noch, table scan) passiert zusammen mit einem riesigen Block, in den tempdb geschrieben wird. Daher kann es wie bei den meisten Dingen von entscheidender Bedeutung sein, ein Benchmarking mit realistischen Daten durchzuführen, bevor diese in der Produktion verwendet werden.