programing

SQL IN() 절의 값 순서로 정렬

newsource 2022. 9. 18. 12:48

SQL IN() 절의 값 순서로 정렬

IN() 절의 값 순서로 주문할 수 있는 방법이 없는지 궁금합니다.

문제는 모든 ID를 취득하는 쿼리와 모든 정보를 취득하는 쿼리가 2개 있다는 것입니다.첫 번째 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를 자동 증분 필드가 있는 임시 테이블에 넣고 두 번째 쿼리에 결합하는 것입니다.

더 좋은 방법이 있을까요?

주의: 첫 번째 쿼리는 "사용자"에 의해 실행되고 두 번째 쿼리는 백그라운드프로세스로 실행되므로 하위 쿼리를 사용하여 두 개의 쿼리를 1개로 결합할 수 없습니다.

MySQL을 사용하고 있습니다만, 다른 DB에도 어떤 옵션이 있는지 알려주시면 도움이 될 것 같습니다.

MySQL 기능 사용:

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을 반환한다.

를 「에, 대로 합니다.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

갑자기 떠오르는 두 가지 솔루션:

  1. order by case id when 123 then 1 when 456 then 2 else null end asc

  2. order by instr(','||id||',',',123,456,') asc

)instr()온 입니다.Oracle이 수 .locate() ★★★★★★★★★★★★★★★★★」charindex()거) ★★★★★★★★★★★★★★★★★★★」

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 데이터베이스에서 작동합니다.

주의: 100개 이상의 레코드 세트를 조회할 때는 작성된 테이블의 두 번째 열(orderTbl.orderIdx)이 필요합니다.원래 orderIdx 열은 없었지만 결과 집합이 100보다 크면 SQL Server Express 2014에서 해당 열을 기준으로 명시적으로 정렬해야 했습니다.

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)

정말 잘 작동했다

정렬된 데이터를 가져옵니다.

SELECT ...
FROM ...
ORDER  BY FIELD(user_id,5,3,2,...,50)  LIMIT 10

IN 절은 일련의 값을 나타내며 집합에는 순서가 없습니다.

가입 후 주문하는 솔루션display_ordercolumn이 가장 올바른 솔루션입니다.그 외의 것은 아마도 DBMS 고유의 해킹일 것입니다(또는 표준 SQL의 OLAP 함수로 작업을 하고 있습니다).확실히 Join은 가장 휴대성이 높은 솔루션입니다(다만,display_order문제가 있을 수 있습니다).주문 열을 선택해야 할 수도 있습니다. 예전에는 표준 SQL에서 필수 조건이었지만, 조금 전에는(아마 SQL-92처럼) 완화되었다고 생각합니다.

MySQL FIND_ 사용IN_SET 함수:

  SELECT * 
    FROM table_name 
   WHERE id IN (..,..,..,..) 
ORDER BY FIND_IN_SET (coloumn_name, .., .., ..);

Oracle의 경우 instr() 함수를 사용하는 John의 솔루션이 작동합니다.다음은 효과가 있었던 약간 다른 솔루션입니다.SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)

방금 이 작업을 수행하려고 했습니다.MS SQL Server에는 FEELD()가 없습니다.

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

복제도 허용하고 있습니다.

한 번 시도해 보세요.

SELECT name, description, ...
WHERE id IN
    (SELECT id FROM table1 WHERE...)
ORDER BY
    (SELECT display_order FROM table1 WHERE...),
    (SELECT name FROM table1 WHERE...)

WHERE는 관련된 서브쿼리가 제대로 작동하도록 하기 위해 약간의 조정이 필요할 수 있지만 기본 원칙은 건전해야 합니다.

처음에는 하나의 쿼리를 작성하려고 했는데, 하나는 사용자에 의해 실행되고 다른 하나는 백그라운드에서 실행되기 때문에 불가능하다고 말씀하셨습니다.사용자로부터 백그라운드프로세스로 전달할 ID 목록을 어떻게 저장합니까?순서를 나타내는 컬럼이 있는 임시 테이블에 넣는 것은 어떨까요?

그럼 이건 어때?

  1. 사용자 인터페이스 비트가 실행되고 사용자가 작성한 새 테이블에 값이 삽입됩니다.ID, 직급 및 일종의 작업 번호 식별자를 삽입합니다.)
  2. 작업 번호가 (모든 ID가 아닌) 백그라운드프로세스에 전달됩니다.
  3. 백그라운드프로세스가 스텝1의 표에서 선택되고 사용자가 참여하면 필요한 기타 정보를 얻을 수 있습니다.WHERE 절의 작업 번호를 사용하고 위치 열별로 정렬합니다.
  4. 백그라운드 프로세스가 완료되면 작업 ID에 따라 테이블에서 삭제됩니다.

단순히 가입만 하면 완벽하기 때문에 해킹이나 복잡한 일이 일어나지 않도록 데이터를 저장해야 한다고 생각합니다.

예를 들어 SQLite에서는 "최근에 재생된" 트랙 ID 목록이 있습니다.

SELECT * FROM recently NATURAL JOIN tracks;

언급URL : https://stackoverflow.com/questions/396748/ordering-by-the-order-of-values-in-a-sql-in-clause