Porządkowanie według kolejności wartości w klauzuli SQL IN()
Zastanawiam się, czy istnieje (być może lepszy sposób) porządkowanie według kolejności wartości w klauzuli IN ().
Problem polega na tym, że mam 2 zapytania, jeden, który pobiera wszystkie identyfikatory, a drugi, który pobiera wszystkie informacje. Pierwszy tworzy kolejność identyfikatorów, które chcę, aby drugi zamówił. Identyfikatory są umieszczane w klauzuli IN() W odpowiedniej kolejności.
Więc byłoby to coś w stylu (bardzo uproszczonym):
SELECT id FROM table1 WHERE ... ORDER BY display_order, name
SELECT name, description, ... WHERE id IN ([id's from first])
Problem polega na tym, że drugie zapytanie nie zwraca wyników w tej samej kolejności, w jakiej identyfikatory są umieszczane w klauzuli IN ().
Jednym z rozwiązań, które znalazłem, jest umieszczenie wszystkich identyfikatorów w tabeli temp z polem automatycznego zwiększania, które jest następnie łączone z drugim zapytaniem.
Czy jest lepsza opcja?Notatka: jako że pierwsze zapytanie jest uruchamiane "przez użytkownika", a drugie jest uruchamiane w procesie w tle, nie ma możliwości połączenia 2 w 1 zapytania przy użyciu podrzędnych zapytań.
Używam MySQL, ale Myślę, że może być przydatne, aby zauważyć, jakie opcje są również dla innych DBs.
13 answers
Użyj MySQL ' s FIELD()
funkcja:
SELECT name, description, ...
FROM ...
WHERE id IN([ids, any order])
ORDER BY FIELD(id, [ids in order])
FIELD()
zwróci indeks pierwszego parametru, który jest równy pierwszemu parametrowi (innemu niż sam pierwszy parametr).
FIELD('a', 'a', 'b', 'c')
Zwróci 1
FIELD('a', 'c', 'b', 'a')
Zwróci 3
To zrobi dokładnie to, co chcesz, Jeśli wkleisz identyfikatory do klauzuli IN()
i funkcji FIELD()
w tej samej kolejności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-30 17:34:12
Zobacz jak sortować dane.
SELECT ...
FROM ...
WHERE zip IN (91709,92886,92807,...,91356)
AND user.status=1
ORDER
BY provider.package_id DESC
, FIELD(zip,91709,92886,92807,...,91356)
LIMIT 10
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-01 09:34:20
Dwa rozwiązania, które przychodzą na myśl:
order by case id when 123 then 1 when 456 then 2 else null end asc
order by instr(','||id||',',',123,456,') asc
(instr()
jest z Oracle; może masz locate()
lub charindex()
lub coś w tym stylu)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-29 06:57:53
Ans, aby uzyskać posortowane dane.
SELECT ...
FROM ...
ORDER BY FIELD(user_id,5,3,2,...,50) LIMIT 10
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-30 09:27:47
Jeśli chcesz wykonać dowolne sortowanie na zapytaniu za pomocą wartości wprowadzonych przez zapytanie w MS SQL Server 2008 + , można to zrobić, tworząc tabelę w locie i wykonując podobne połączenie (używając nomenklatury z OP).
SELECT table1.name, table1.description ...
FROM (VALUES (id1,1), (id2,2), (id3,3) ...) AS orderTbl(orderKey, orderIdx)
LEFT JOIN table1 ON orderTbl.orderKey=table1.id
ORDER BY orderTbl.orderIdx
Jeśli zamienisz polecenie VALUES na coś innego, co robi to samo, ale w ANSI SQL, to powinno to działać na dowolnej bazie danych SQL.
Uwaga: Druga kolumna w utworzonej tabeli (orderTbl.orderIdx) jest konieczne przy zapytaniu zestawy rekordów większe niż 100 lub więcej. Początkowo nie miałem kolumny orderIdx, ale okazało się, że z zestawami wyników większych niż 100 musiałem wyraźnie sortować według tej kolumny; w SQL Server Express 2014 tak czy inaczej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-08 22:50:44
Klauzula IN opisuje zbiór wartości, a zestawy nie mają porządku.
Twoje rozwiązanie z join, a następnie zamówienie na kolumnie display_order
jest najbardziej poprawnym rozwiązaniem; Wszystko inne jest prawdopodobnie specyficznym dla DBMS hack(lub robi coś z funkcjami OLAP w standardowym SQL). Z pewnością join jest najbardziej przenośnym rozwiązaniem (choć generowanie danych z wartościami display_order
może być problematyczne). Zauważ, że może być konieczne wybranie kolumn zamawiających; które używane do być wymogiem w standardowym SQL, choć uważam, że był zrelaksowany z reguły jakiś czas temu (może tak dawno temu, jak SQL-92).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-29 07:02:59
W przypadku Oracle rozwiązanie Johna za pomocą funkcji instr() działa. Oto nieco inne rozwiązanie, które zadziałało -
SELECT id
FROM table1
WHERE id IN (1, 20, 45, 60)
ORDER BY instr('1, 20, 45, 60', id)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-31 23:54:19
SELECT ORDER_NO, DELIVERY_ADDRESS
from IFSAPP.PURCHASE_ORDER_TAB
where ORDER_NO in ('52000077','52000079','52000167','52000297','52000204','52000409','52000126')
ORDER BY instr('52000077,52000079,52000167,52000297,52000204,52000409,52000126',ORDER_NO)
Pracował naprawdę świetnie
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-05 11:43:15
Użyj MySQL FIND_IN_SET function:
SELECT *
FROM table_name
WHERE id IN (..,..,..,..)
ORDER BY FIND_IN_SET (coloumn_name, .., .., ..);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-21 16:34:32
Moją pierwszą myślą było napisanie pojedynczego zapytania, ale powiedziałeś, że nie jest to możliwe, ponieważ jedno jest uruchamiane przez użytkownika, a drugie jest uruchamiane w tle. Jak przechowujesz listę identyfikatorów, które mają zostać przekazane od użytkownika do procesu w tle? Dlaczego nie umieścić ich w tymczasowej tabeli z kolumną, aby określić kolejność.
Więc co powiesz na to:
- bit interfejsu użytkownika uruchamia i wstawia wartości do nowej utworzonej tabeli. Wstawia id, pozycję i jakieś zadanie numer identyfikacyjny)
- numer zadania jest przekazywany do procesu w tle (zamiast wszystkich identyfikatorów)
- proces w tle wykonuje select z tabeli w kroku 1, a Ty dołączasz, aby uzyskać inne wymagane informacje. Używa numeru zadania w klauzuli WHERE i zleceń w kolumnie position.
- proces w tle, po zakończeniu, usuwa z tabeli na podstawie identyfikatora zadania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-28 23:50:39
Myślę, że powinieneś przechować swoje dane w taki sposób, aby po prostu zrobić połączenie i będzie idealne, więc nie ma hacków i skomplikowanych rzeczy się dzieje.
Mam na przykład listę" ostatnio odtwarzanych " idów utworów, na SQLite po prostu robię:
SELECT * FROM recently NATURAL JOIN tracks;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 18:32:56
Daj temu szansę:
SELECT name, description, ...
WHERE id IN
(SELECT id FROM table1 WHERE...)
ORDER BY
(SELECT display_order FROM table1 WHERE...),
(SELECT name FROM table1 WHERE...)
WHEREs prawdopodobnie będzie wymagało trochę poprawek, aby skorelowane zapytania działały poprawnie, ale podstawowa zasada powinna być dźwiękowa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-28 22:17:27
Właśnie próbowałem zrobić to jest MS SQL Server gdzie nie mamy pola ():
SELECT table1.id
...
INNER JOIN
(VALUES (10,1),(3,2),(4,3),(5,4),(7,5),(8,6),(9,7),(2,8),(6,9),(5,10)
) AS X(id,sortorder)
ON X.id = table1.id
ORDER BY X.sortorder
Zauważ, że ja również zezwalam na powielanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-16 10:13:33