2013-05-31 9 views
7

Ich habe eine Abfrage, die eine benutzerdefinierte Sortierung benötigt, getrimmt bis auf den blanken Minima so etwas wie:Individuelle MySQL Bestell

SELECT u.*, p.*, p.id as product_id 
FROM users u, products p 
WHERE u.id = p.user_id 
ORDER BY product_id DESC 

und ich bekomme eine Menge von Zeilen wie zurückgegeben:

UserID  ProductID 
    2    5 
    2    4 
    3    3 
    1    2 
    1    1 

Aber ich will es eigentlich so etwas wie diese sortieren (also kein 2 UserIDs zu ihnen benachbart ist):

UserID  ProductID 
    1    2 
    2    4 
    3    3 
    2    5 
    1    1 

Ist dies überhaupt möglich wit h MySQL, oder brauche ich etwas PHP Magie?

+0

Wie würden Sie sort [1,2], wenn sie nicht benachbart sein können? Ist [1,3,5] eine gültige Sortierreihenfolge oder wird [1,5,3] benötigt? –

+0

das braucht etwas Logik. Selbst 'FIELD()' von mysql wird nicht helfen. – Pedigree

+0

Was ich meinte war, [1,1,2,2,3] ist eine schlechte Sortierung für die UserIDs, ich brauche die UserId nebeneinander zu verschiedenen Zahlen, es ist okay, wenn es 2 zu 1 oder 3 zu 2 ist, nur nicht 1 zu 1 oder 2 zu 2. –

Antwort

0

Hier holen Sie Ihre sortierten Ergebnisse in ein Array. Dann mach sowas.

$records = $res->fetchAll(); 
$count = count($records); 
$records = array_chunk($records, ceil(count($records)/2); 
$unsorted = array(); 
for($x = 0; $x < $count; $x++){ 
     $unsorted[] = $records[$x%2][floor($x/2)]; 
} 
1

Ein kanonischer Weg, dieses Problem zu lösen, ist durch die doppelten Zeilen aufzählt und dann von diesem Wert der Bestellung:

select t.* 
from (SELECT u.*, p.*, p.id as product_id, 
      row_number() over (partition by u.id order by (select NULL)) as seqnum 
     FROM users u join 
      products p 
      on u.id = p.user_id 
    ) t 
order by seqnum, id; 

Dies wird, solange niemand hat eine wirklich lange Sequenz arbeiten (wie in Ihrem Beispiel).

Es gibt keine "always-works" -Lösung, weil es einfach ist, eine Situation zu finden, in der Ihr Ziel nicht möglich ist.

-1

Also, wenn Ihr Problem ist nur, dass Sie zwei Datensätze mit derselben ID nicht wollen, sollten nicht nebeneinander wha komme ich einfachste denken kann, ist

SELECT u.*, p.*, p.id as product_id 
FROM users u, products p 
WHERE u.id = p.user_id 
ORDER BY user_id%2 DESC 

verwenden Sie können aber auch andere Zahl als 2 verwenden, um treffen jede bestimmte Reihenfolge Sie wollen ....

+0

Ich vermisse etwas, aber wie hat das Sortieren auf etwas, das von der Produkt-ID abgeleitet ist, alles andere als einen Randomisierungseffekt auf die Benutzer-ID-Reihenfolge und verhindert somit benachbarte gleiche Werte? –

+0

ya danke James hat die Antwort repariert – balaji

0

Betrachten Sie die folgende ...

CREATE TABLE sortable(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,player_id INT NOT NULL); 

INSERT INTO sortable(player_id) VALUES (1),(1),(2),(3),(4),(3),(3),(2),(1),(2),(4),(4); 

SELECT * FROM sortable; 
+----+-----------+ 
| id | player_id | 
+----+-----------+ 
| 1 |   1 | 
| 2 |   1 | 
| 3 |   2 | 
| 4 |   3 | 
| 5 |   4 | 
| 6 |   3 | 
| 7 |   3 | 
| 8 |   2 | 
| 9 |   1 | 
| 10 |   2 | 
| 11 |   4 | 
| 12 |   4 | 
+----+-----------+ 

SELECT x.*,COUNT(*) rank FROM sortable x JOIn sortable y ON y.player_id = x.player_id AND y.id <= x.id GROUP BY x.id ORDER BY player_id,rank; 
+----+-----------+------+ 
| id | player_id | rank | 
+----+-----------+------+ 
| 1 |   1 | 1 | 
| 2 |   1 | 2 | 
| 9 |   1 | 3 | 
| 3 |   2 | 1 | 
| 8 |   2 | 2 | 
| 10 |   2 | 3 | 
| 4 |   3 | 1 | 
| 6 |   3 | 2 | 
| 7 |   3 | 3 | 
| 5 |   4 | 1 | 
| 11 |   4 | 2 | 
| 12 |   4 | 3 | 
+----+-----------+------+ 

SELECT x.*,COUNT(*) rank FROM sortable x JOIn sortable y ON y.player_id = x.player_id AND y.id <= x.id GROUP BY x.id ORDER BY rank; 
+----+-----------+------+ 
| id | player_id | rank | 
+----+-----------+------+ 
| 1 |   1 | 1 | 
| 3 |   2 | 1 | 
| 4 |   3 | 1 | 
| 5 |   4 | 1 | 
| 2 |   1 | 2 | 
| 8 |   2 | 2 | 
| 6 |   3 | 2 | 
| 11 |   4 | 2 | 
| 9 |   1 | 3 | 
| 10 |   2 | 3 | 
| 7 |   3 | 3 | 
| 12 |   4 | 3 | 
+----+-----------+------+