SQL IN () 절의 값 순서에 따른 순서
IN () 절의 값 순서대로 정렬 할 수있는 방법이 있는지 궁금합니다.
문제는 두 개의 쿼리가 있다는 것입니다. 하나는 모든 ID를 가져오고 두 번째는 모든 정보를 검색합니다. 첫 번째는 두 번째로 주문하려는 ID의 순서를 만듭니다. ID는 IN () 절에 올바른 순서로 배치됩니다.
따라서 (매우 단순화 된) 것과 같습니다.
SELECT id FROM table1 WHERE ... ORDER BY display_order, name
SELECT name, description, ... WHERE id IN ([id's from first])
문제는 두 번째 쿼리가 ID를 IN () 절에 넣는 것과 같은 순서로 결과를 반환하지 않는다는 것입니다.
내가 찾은 한 가지 해결책은 모든 ID를 자동 증분 필드가있는 임시 테이블에 넣은 다음 두 번째 쿼리에 조인하는 것입니다.
더 나은 옵션이 있습니까?
참고 : 첫 번째 쿼리는 "사용자에 의해"실행되고 두 번째 쿼리는 백그라운드 프로세스에서 실행되므로 하위 쿼리를 사용하여 2 개를 1 개 쿼리로 결합 할 수있는 방법이 없습니다.
MySQL을 사용하고 있지만 다른 DB에도 어떤 옵션이 있는지 기록해 두는 것이 도움이 될 수 있다고 생각합니다.
MySQL의 FIELD()
기능을 사용하십시오 :
SELECT name, description, ...
FROM ...
WHERE id IN([ids, any order])
ORDER BY FIELD(id, [ids in order])
FIELD()
첫 번째 매개 변수 자체와 다른 첫 번째 매개 변수와 동일한 첫 번째 매개 변수의 인덱스를 반환합니다.
FIELD('a', 'a', 'b', 'c')
1을 반환합니다
FIELD('a', 'c', 'b', 'a')
3을 반환합니다
이것은 id를 IN()
절과 FIELD()
함수에 같은 순서 로 붙여 넣으면 원하는 것을 정확하게 수행합니다 .
정렬 된 데이터를 얻는 방법은 다음을 참조하십시오.
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
떠오르는 두 가지 솔루션 :
order by case id when 123 then 1 when 456 then 2 else null end asc
order by instr(','||id||',',',123,456,') asc
( instr()
Oracle에서이며, 어쩌면 당신이 locate()
나 charindex()
또는 같은)
정렬 된 데이터를 얻습니다.
SELECT ...
FROM ...
ORDER BY FIELD(user_id,5,3,2,...,50) LIMIT 10
MS SQL Server 2008+ 의 쿼리에서 입력 한 값을 사용하여 쿼리에서 임의의 정렬을 수행하려는 경우 즉시 테이블을 생성하고 조인 (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
VALUES 문을 동일하지만 ANSI SQL의 다른 것으로 바꾸면 모든 SQL 데이터베이스에서 작동합니다.
참고 : 생성 된 테이블의 두 번째 열 (orderTbl.orderIdx)은 100보다 큰 레코드 세트를 쿼리 할 때 필요합니다. 원래 orderIdx 열이 없었지만 결과 집합이 100보다 큰 경우 해당 열을 기준으로 명시 적으로 정렬해야한다는 것을 알았습니다. 어쨌든 SQL Server Express 2014에서.
IN 절은 값 세트를 설명하며 세트에는 순서가 없습니다.
Your solution with a join and then ordering on the display_order
column is the most nearly correct solution; anything else is probably a DBMS-specific hack (or is doing some stuff with the OLAP functions in standard SQL). Certainly, the join is the most nearly portable solution (though generating the data with the display_order
values may be problematic). Note that you may need to select the ordering columns; that used to be a requirement in standard SQL, though I believe it was relaxed as a rule a while ago (maybe as long ago as SQL-92).
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)
worked really great
For Oracle, John's solution using instr() function works. Here's slightly different solution that worked - SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)
Use MySQL FIND_IN_SET function:
SELECT *
FROM table_name
WHERE id IN (..,..,..,..)
ORDER BY FIND_IN_SET (coloumn_name, .., .., ..);
My first thought was to write a single query, but you said that was not possible because one is run by the user and the other is run in the background. How are you storing the list of ids to pass from the user to the background process? Why not put them in a temporary table with a column to signify the order.
So how about this:
- The user interface bit runs and inserts values into a new table you create. It would insert the id, position and some sort of job number identifier)
- The job number is passed to the background process (instead of all the ids)
- The background process does a select from the table in step 1 and you join in to get the other information that you require. It uses the job number in the WHERE clause and orders by the position column.
- The background process, when finished, deletes from the table based on the job identifier.
I think you should manage to store your data in a way that you will simply do a join and it will be perfect, so no hacks and complicated things going on.
I have for instance a "Recently played" list of track ids, on SQLite i simply do:
SELECT * FROM recently NATURAL JOIN tracks;
Give this a shot:
SELECT name, description, ...
WHERE id IN
(SELECT id FROM table1 WHERE...)
ORDER BY
(SELECT display_order FROM table1 WHERE...),
(SELECT name FROM table1 WHERE...)
The WHEREs will probably take a little tweaking to get the correlated subqueries working properly, but the basic principle should be sound.
I just tried to do this is MS SQL Server where we do not have FIELD():
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
Note that I am allowing duplication too.
참고URL : https://stackoverflow.com/questions/396748/ordering-by-the-order-of-values-in-a-sql-in-clause
'development' 카테고리의 다른 글
한 PC에서 다른 PC로 Jenkins를 이동하는 방법 (0) | 2020.06.19 |
---|---|
JavaScript로 날짜 시간을 얻는 방법? (0) | 2020.06.19 |
Java로 플러그인 시스템을 구축하는 가장 좋은 방법 (0) | 2020.06.19 |
CMake?를 사용하여 폴더의 모든 파일을 대상에 자동으로 추가 하시겠습니까? (0) | 2020.06.19 |
파이썬에서 메소드를 재정의하고 있음을 어떻게 표시합니까? (0) | 2020.06.19 |