2011-12-03 5 views
6

Powiedzmy, że chcemy odzyskać 100 rekordów z tabeli o nazwie messages, i chcę je uzyskać w następujący sposób:Czy można połączyć SELECT w SQL?

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

Czy istnieje jakiś sposób, aby to skutecznie zrobić? Jakie byłoby odpowiednie zapytanie? Czy powinienem wykonać zapytanie, aby wybrać pierwsze 50, zapytanie, aby wybrać ostatnie 50, a następnie połączyć wyniki?

+0

Jest to jeden przypadek, w którym to pewnie zrobić dwie kwerendy i scalić je w kodzie aplikacji. Prawdopodobnie można to zrobić w jednym zapytaniu, tworząc numery wierszy i używając bardzo inteligentnego warunkowego polecenia "ORDER BY", ale byłoby o wiele łatwiej zrobić w kodzie aplikacji. –

+0

Tak, myślałem tak samo ... Prawdopodobnie łatwiejsze/bardziej wydajne jest zrobienie tego za pomocą dwóch różnych zapytań i połączenie ich wyników w kod – federicot

+0

Zdecydowanie poczekałbym, czy ktoś tutaj może stworzyć genialne rozwiązanie. Jest tu kilka całkiem sprytnych ludzi. –

Odpowiedz

2

Spróbuj jeśli Twój ID to ciąg liczb:

Pierwszy

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

Następnie

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

dla limitu 100, trywialne "LIMIT 100" na końcu zapytania ... –

+0

"ASC" na końcu powinno być 'DESC'. Poza tym działa to doskonale i jest to najprostsze rozwiązanie. Dzięki! – federicot

+0

Trochę za późno, aby zapytać ... ale co, jeśli zamiast ordynacji przez 'id' zamawiam przez' timestamp' (używając 'UNIX_TIMESTAMP (timestamp)')? – federicot

0

Chodzi o to, aby stworzyć dwa wirtualne kolumny "serie_order" (wariant) oraz " serie "(stałe) będziesz używać obu części danych (będziesz musiał podzielić dane na dwie części).

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

Niestety w MySQL brakuje funkcji 'generate_series()'. – pilcrow

+0

To było tylko używane jako dane wirtualne, edytowałem przy użyciu tabeli "komunikatów" – 131

+0

To jest właściwy pomysł, ale nie do końca poprawny. Nagie "*" musi znajdować się na pierwszym miejscu w SELECTs, w przeciwnym razie jest to błąd składniowy. Oddzielnie, co jeśli "wiadomości" ma, powiedzmy, 200 wierszy? Na marginesie nie potrzebujesz najgłębszych tabel pochodnych, ponieważ możesz po prostu wybrać serię SELECT 1 AS, 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

Prawie! "new_order" 1 i "new_order" 100 stają się równe 0 w klauzuli ORDER BY, a 2 i 99 stają się 1 itd. Jak MySQL wie, który rekord umieścić jako pierwszy? Potrzebujesz innych kryteriów ORDER BY, jak w [tej odpowiedzi] (http://stackoverflow.com/a/8371930/132382), aby zagwarantować prawidłowe wyniki. – pilcrow