Czy możliwe jest sortowanie w mysql według „kolejności według” przy użyciu predefiniowanego zestawu wartości kolumn (ID), takich jak: order by (ID = 1,5,4,3), aby uzyskać rekord 1, 5, 4, 3 w tym rozkazać?
UPDATE: O nadużywaniu mysql ;-) Muszę wyjaśnić, dlaczego tego potrzebuję ...
Chcę, aby moje rekordy zmieniały się losowo co 5 minut. Mam zadanie crona, aby zrobić tabelę aktualizacji, aby umieścić w niej inny, losowy porządek sortowania. Jest tylko jeden problem! PAGINACJA. Będę miał gościa, który wejdzie na moją stronę i dam mu pierwsze 20 wyników. Poczeka 6 minut i przejdzie do strony 2, a wyniki będą błędne, ponieważ kolejność sortowania już się zmieniła.
Pomyślałem więc, że jeśli przychodzi do mojej witryny, umieszczam wszystkie identyfikatory w sesji, a kiedy jest na stronie 2, otrzymuje prawidłowe rekordy, nawet jeśli sortowanie już się zmieniło.
Czy jest inny, lepszy sposób, aby to zrobić?
Odpowiedzi:
Możesz użyć funkcji ORDER BY i FIELD. Zobacz http://lists.mysql.com/mysql/209784
SELECT * FROM table ORDER BY FIELD(ID,1,5,4,3)
Używa funkcji Field () , która "Zwraca indeks (pozycję) str na liście str1, str2, str3, .... Zwraca 0 jeśli str nie zostanie znaleziony" zgodnie z dokumentacją. Czyli w rzeczywistości sortujesz wynik według wartości zwracanej przez tę funkcję, która jest indeksem wartości pola w danym zestawie.
źródło
Powinieneś być w stanie użyć
CASE
do tego:ORDER BY CASE id WHEN 1 THEN 1 WHEN 5 THEN 2 WHEN 4 THEN 3 WHEN 3 THEN 4 ELSE 5 END
źródło
W oficjalnej dokumentacji mysql dotyczącej ORDER BY ktoś napisał, że możesz użyć
FIELD
w tej sprawie, na przykład:SELECT * FROM table ORDER BY FIELD(id,1,5,4,3)
To niesprawdzony kod, który w teorii powinien działać.
źródło
SELECT * FROM table ORDER BY id='8' DESC, id='5' DESC, id='4' DESC, id='3' DESC
Gdybym miał na przykład 10 rejestrów, w ten sposób ID 1, 5, 4 i 3 pojawią się jako pierwsze, a pozostałe rejestry pojawią się jako następne.
Wystawa normalna 1 2 3 4 5 6 7 8 9 10
W ten sposób
8 5 4 3 1 2 6 7 9 10
źródło
Jest inny sposób rozwiązania tego problemu. Dodaj oddzielną tabelę, coś takiego:
CREATE TABLE `new_order` ( `my_order` BIGINT(20) UNSIGNED NOT NULL, `my_number` BIGINT(20) NOT NULL, PRIMARY KEY (`my_order`), UNIQUE KEY `my_number` (`my_number`) ) ENGINE=INNODB;
Ta tabela będzie teraz używana do definiowania własnego mechanizmu zamówień.
Dodaj tam swoje wartości:
my_order | my_number ---------+---------- 1 | 1 2 | 5 3 | 4 4 | 3
... a następnie zmodyfikuj instrukcję SQL, dołączając do nowej tabeli.
SELECT * FROM your_table AS T1 INNER JOIN new_order AS T2 on T1.id = T2.my_number WHERE ....whatever... ORDER BY T2.my_order;
To rozwiązanie jest nieco bardziej złożone niż inne rozwiązania, ale korzystając z niego nie musisz zmieniać swojego
SELECT
oświadczenia za każdym razem, gdy zmienią się Twoje kryteria zamówienia - wystarczy zmienić dane w tabeli zamówień.źródło
Jeśli chcesz najpierw zamówić pojedynczy identyfikator w wyniku, użyj id.
select id,name from products order by case when id=5 then -1 else id end
Jeśli chcesz zacząć od sekwencji wielu identyfikatorów, określ kolekcję, podobnie jak w przypadku
IN
instrukcji.select id,name from products order by case when id in (30,20,10) then -1 else id end,id
źródło
Jeśli chcesz zamówić pojedynczy identyfikator jako ostatni w wyniku, użyj kolejności według przypadku. (Np .: chcesz, aby opcja „inne” znajdowała się na liście ostatnich miast, a wszystkie miasta były wyświetlane w porządku alfabetycznym).
select id,city from city order by case when id = 2 then city else -1 end, city ASC
Gdybym na przykład miał 5 miast, chciałbym pokazać miasto w porządku alfabetycznym z opcją „inne” wyświetlaną jako ostatnią na liście rozwijanej, wtedy możemy użyć tego zapytania. zobacz przykład inne są wyświetlane w mojej tabeli pod drugim identyfikatorem (id: 2), więc używam „when id = 2” w powyższym zapytaniu.
rekord w tabeli DB:
moje wyjście:
źródło
SELECT * FROM TABLE ORDER BY (columnname,1,2) ASC OR DESC
źródło
ASC OR DESC
jest to właściwa składniaFIELD
funkcji, która jest identyczna z akceptowaną odpowiedzią sprzed 8 lat.