2016-04-29 3 views
2

Ich mag Zeilen in zufälliger Reihenfolge auszuwählen, indem durch group_id sortierte:ORDER BY rand() und die Gruppe mit group_id

id group_id 
1 1 
2 1 
3 2 
4 2 
5 3 
6 4 

ich sie gerne möchte unten oder randomisierte, aber immer noch gruppiert sortiert werden:

id group_id 
5 3 
3 2 
4 2 
1 1 
2 1 
6 4 

Unten wird sie sortieren, aber ich möchte die Art zufällig sein. Wie erreiche ich das?

Unten ist eine Beispielabfrage, die ich für die tatsächliche Anwendung herausfinden werde.

SELECT * FROM (SELECT requests.*, accounts.username, accounts.password 
FROM requests LEFT JOIN accounts ON requests.acc_id = accounts.id 
WHERE requests.status NOT IN(1) AND accounts.status=1 ORDER BY RAND() 
) AS subquery GROUP BY acc_id 
+0

Ich brauchte eine Weile, um es herauszufinden, aber Sie möchten _randomly_ auf 'group_id' richtig sortieren? Mit anderen Worten, Sie möchten eine zufällige Reihenfolge, in der alle Zeilen mit der gleichen 'group_id' nebeneinander liegen? – Rick

+0

Sie sollten 'ORDER BY RAND()' nicht verwenden, da mysql nicht nur angewiesen wird, "werfen Sie bitte alle Indizes weg", sondern auch "schreiben Sie die gesamte Ergebnismenge auf einen Datenträger und verwenden Sie filesort". Ihre Tabelle könnte jetzt klein genug sein, dass dies nicht bemerkbar ist, aber dies wird * exponentiell schlechter *, wenn die Datenmenge wächst. – Sammitch

Antwort

3

Sie könnten versuchen Bestellung durch eine Zufallszahl mit einem Samen abhängig von den group_id, noch mit einem zufälligen Faktor. So:

SET @seed = 100*RAND(); 
SELECT * FROM table ORDER BY RAND(group_id*@seed); 
+1

das funktioniert super! Kannst du bitte deine Logik dahinter erklären? Danke – fawzib

+0

Geben Sie die 'RAND()' Funktion ein Argument bindet das Ergebnis an die Eingabe - z. Die Wertefolge von RAND ist für die gleichen Initialisierer immer gleich. Plus - (aus dem MySQL 'RAND()' docs) "Wenn ein nichtkonstanter Initialisierer (wie ein Spaltenname) als Argument verwendet wird, wird der Startwert mit dem Wert für jeden Aufruf von' RAND() 'initialisiert.". Also, 'RAND (group_id)' gibt eine konstante Pseudozufallszahl basierend auf 'group_id', die wir anordnen können und das erwartete Ergebnis erhalten. Der zufällige Startwert für den Initialisierer stellt nur sicher, dass das Ergebnis bei jeder Abfrageausführung unterschiedlich ist. –

+0

Wie hat die Neuinitialisierung des Pseudozufallsgenerators für jede Zeile einen Vorteil gegenüber nur 'ORDER BY RAND()'?Mit dem Muster in dieser Antwort wird die Reihenfolge der Zeilen im Wesentlichen durch die anfängliche Einstellung von @seed "fixiert". – spencer7593

0

Sie eine Unterabfrage verwenden könnte, die zufällig Aufträge alle Gruppen-IDs und mit einer Benutzervariablen ihnen eine Position zuweist. Verbinden Sie sich dann mit der Originaltabelle und ordnen Sie sie an der Position an.

SELECT t1.id, t1.group_id 
FROM yourTable AS t1 
JOIN (SELECT group_id, @position := @position + 1 as position 
     FROM (SELECT DISTINCT(group_id) AS group_id 
      FROM yourTable 
      ORDER BY RAND()) AS x 
     CROSS JOIN (SELECT @position := 0) AS var) AS t2 
ON t1.group_id = t2.group_id 
ORDER BY position, id 

DEMO

0

verstehe ich nicht, warum die anderen Antworten als beteiligt sind, wie sie sind. Wenn Sie die Zeilen in einer zufälligen Reihenfolge benötigen, tun Sie einfach ORDER BY RAND().

SELECT t.id 
    , t.group_id 
    FROM `table` t 
ORDER BY RAND() 

Beachten Sie, dass RAND() nicht wirklich zufällig ist, ist es ein Pseudo -random Generator.


Ich verstehe nicht, warum Sie eine Inline-Ansicht benötigen. Sie können den GROUP BY-Vorgang ohne eine Inline-Ansicht ausführen. Angesichts der GROUP BY-Anweisung muss in der Inline-Ansicht keine unnötige ORDER BY-Operation ausgeführt werden.

SELECT requests.* 
     , accounts.username 
     , accounts.password 
    FROM requests 
    LEFT 
    JOIN accounts 
    ON requests.acc_id = accounts.id 
    WHERE requests.status NOT IN(1) 
    AND accounts.status=1 
    GROUP 
    BY acc_id 
    ORDER 
    BY RAND()