2013-05-31 11 views
7

Ho una domanda che ha bisogno di un ordinamento personalizzato, tagliato fino ai minimi nudi qualcosa come:personalizzato MySQL per l'ordinazione

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

E ho restituito un insieme di righe come:

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

Ma voglio che ordinare in realtà qualcosa di simile (in modo da non 2 UserIDs sono adiacenti a vicenda):

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

è questo persino possibile ingegno h MySQL, o ho bisogno di qualche magia PHP?

+0

Come ti sorta [1,2], se non possono essere adiacenti? [1,3,5] è un ordinamento valido o è richiesto [1,5,3]? –

+0

questo richiede un po 'di logica. anche mysql's 'FIELD()' non aiuta. – Pedigree

+0

Quello che intendevo era, [1,1,2,2,3] è un cattivo ordinamento per gli UserID, ho bisogno che gli UserId adiacenti siano numeri diversi, va bene se è 2 o 1 o 3 o 2, solo non 1 a 1 o 2 a 2. –

risposta

0

Qui preleva i risultati ordinati in un array. Quindi fai qualcosa di simile.

$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

Un modo canonico di risolvere questo problema è enumerando le righe duplicate e poi ordinare da quel valore:

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; 

Questo funziona, a patto che non un utente ha una davvero lunga sequenza (come nel tuo esempio).

Non esiste una soluzione "sempre funzionante", perché è facile arrivare a una situazione in cui il proprio obiettivo non è possibile.

-1

Così, se il problema è solo che non volete due record con lo stesso ID non dovrebbe venire uno accanto all'altro wha posso pensare più semplice è utilizzare

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 

o si può anche usare altro numero di 2 a soddisfare qualsiasi certo ordine che si desidera ....

+0

Potrei mancare qualcosa, ma in che modo l'ordinamento su qualcosa derivato dall'ID prodotto ha qualcosa di diverso da un effetto randomizzante sull'ordinamento ID utente, e quindi previene valori uguali adiacenti? –

+0

ya grazie James ha risolto la risposta – balaji

0

si consideri il seguente ...

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 | 
+----+-----------+------+ 
Problemi correlati