2011-12-03 11 views
6

Diciamo che voglio recuperare 100 record da una tabella denominata messages, e voglio ottenerli seguente modo:È possibile unire in un SELECT in SQL?

1st message 
100th message 
2nd message 
99th message 
3rd message 
98th message 
(...) 

Esiste un modo per fare questo in modo efficace ? Quale sarebbe la query appropriata? Oppure devo fare una query per selezionare i primi 50, una query per selezionare gli ultimi 50 e quindi unire i risultati?

+0

questo è un caso in cui avrei probabilmente fare due query e unirli nel codice dell'applicazione. Può probabilmente essere fatto in una query creando numeri di riga e usando un condizionale molto intelligente 'ORDER BY', ma sarebbe molto più facile da fare nel codice dell'applicazione. –

+0

Sì, ho pensato lo stesso ... Probabilmente è più facile/più efficiente farlo con due query diverse e unire i loro risultati nel codice – federicot

+0

Aspetterei sicuramente di vedere se qualcuno qui può produrre una soluzione geniale. Ci sono alcune persone abbastanza intelligenti qui intorno. –

risposta

2

Prova se l'ID è una sequenza di numeri:

Prima

SET @half = (SELECT MAX(id) FROM messages)/2; 

Poi

SELECT * FROM `messages` ORDER BY (IF(id<@half,@half*2-id,id-1)) DESC,id ASC; 
+0

per il limite di 100, banale 'LIMIT 100' alla fine della query ... –

+0

Il' ASC' alla fine, dovrebbe essere 'DESC'. A parte questo, questo funziona perfettamente ed è la soluzione più semplice di tutti questi. Grazie! – federicot

+0

Un po 'troppo tardi per chiedere ... ma cosa succede se, invece di ordinare per 'id' sto ordinando per' timestamp' (usando 'UNIX_TIMESTAMP (timestamp)')? – federicot

0

Il punto è quello di creare due colonne virtuali "serie_order" (variante) e " serie "(costante) che userai su entrambe le parti dei tuoi dati (dovrai dividere i tuoi dati in due).

SELECT * FROM (
    SELECT 1 as serie, message_id AS serie_order , * FROM 
    (SELECT message_id FROM messages) as part_up 
UNION 
    SELECT 2 as serie, 101-message_id as serie_order, * FROM 
    (SELECT message_id FROM messages) as part_down 
) AS world 

ORDER BY serie_order ASC, serie ASC 
LIMIT 100 
+0

Purtroppo MySQL manca di una funzione 'generate_series()'. – pilcrow

+0

Questo è stato appena usato come dati virtuali, ho modificato usando la tabella "messaggi" – 131

+0

Questa è l'idea giusta ma non del tutto corretta. Il semplice "*" deve venire prima in SELECT, altrimenti si tratta di un errore di sintassi. Separatamente, cosa succede se "messaggi" ha, diciamo, 200 righe? Per inciso, non hai bisogno delle tabelle derivate più interne, dato che potresti semplicemente selezionare SELECT 1 AS serie, message_id AS serie_order, message_id FROM messages'. – pilcrow

0
set @rank:=0; 

select id from 
(select id, @rank:=(coalesce(@rank, 0)+1) as new_order 
from a_table 
order by some_column limit 100) as ordering 
order by if (new_order<=50, new_order-1, abs(100-new_order)) asc; 
+1

Quasi! "new_order" 1 e "new_order" 100 diventano entrambi 0 nella tua clausola ORDER BY, e 2 e 99 diventano 1, ecc. In che modo MySQL sa quale record inserire per primo? È necessario un secondo criterio ORDER BY, come in [questa risposta] (http://stackoverflow.com/a/8371930/132382), per garantire l'output corretto. – pilcrow

Problemi correlati