itsource

SQL "IN" 절에서 튜플 사용

mycopycode 2023. 6. 21. 22:35
반응형

SQL "IN" 절에서 튜플 사용

group_id 및 group_type 필드가 포함된 테이블이 있는데, 이 테이블에서 튜플 목록에서 튜플(그룹 ID, 그룹 유형)이 있는 모든 레코드를 쿼리하려고 합니다.예를 들어 다음과 같은 작업을 수행할 수 있습니다.

SELECT *
FROM mytable
WHERE (group_id, group_type) IN (("1234-567", 2), ("4321-765", 3), ("1111-222", 5))

sql in 절에서 튜플을 사용하는 것과 매우 유사한 질문이 이미 에 있지만, 제안된 솔루션은 튜플 목록을 다른 테이블에서 가져올 것으로 가정합니다.이 경우 튜플 값이 하드 코딩되어 있기 때문에 작동하지 않습니다.

한 가지 해결책은 문자열 연결을 사용하는 것입니다.

SELECT *
FROM mytable
WHERE group_id + STR(group_type, 1) IN ("1234-5672", "4321-7653", "1111-2225")

그러나 문제는 테이블이 상당히 크고 각 레코드에 대해 문자열 연결 및 변환을 수행하는 데 비용이 매우 많이 든다는 것입니다.

제안할 것이 있습니까?

매우 작은 수정이 주어지면 (큰따옴표를 단일 따옴표로 바꾸고 다음을 추가합니다.VALUES키워드), 제안한 구문이 유효한 표준 SQL-92 구문입니다.

SELECT *
  FROM mytable
 WHERE (group_id, group_type) IN (
                                  VALUES ('1234-567', 2), 
                                         ('4321-765', 3), 
                                         ('1111-222', 5)
                                 );

안타깝게도 MSFT는 이 기능을 SQL Server에 추가하지 않았으며 '계획되지 않은' 기능으로 간주하고 있습니다.

FWIW PostgreSQL 및 SQLite는 이 구문을 지원하는 SQL 제품의 예입니다.

SQL Server 2008에서는 다음과 같은 작업을 수행할 수 있습니다.

select *
from mytable as T
where exists (select *
              from (values ('1234-567', 2), 
                           ('4321-765', 3), 
                           ('1111-222', 5)) as V(group_id, group_type)
              where T.group_id = V.group_id and
                    T.group_type = V.group_type               
             )

편집: 이 답변은 날짜가 지정된 답변입니다. 2011년에 승인된 답변이지만, 더 많은 표를 가진 다른 답변은 더 최근의 접근 방식을 반영합니다.

OR 문을 구성하는 것이 어떻습니까?

SELECT *
FROM mytable 
WHERE (group_id = '1234-567' and group_type = 2)
    OR (group_id = '4321-765' and group_type = 3)
    OR (group_id = '1111-222' and group_type = 5)

물론, 당신의 컨셉 예처럼 멋지고 깔끔해 보이지는 않지만, 그것은 그 일을 할 것입니다(그리고 만약 당신이IN튜플이 존재했다면, 커버 아래에서 정확히 같은 방식으로 구현했을 것입니다.

공통 테이블 식을 사용하여 다음 튜플이 다른 테이블에 있는 것처럼 가장할 수 있습니다.

;WITH Tuples as (
     select '1234-567' as group_id, 2 as group_type union all
     select '4321-765', 3 union all
     select '1111-222', 5
)
SELECT * /* TODO - Pick appropriate columns */
from mytable m where exists (
   select * from Tuples t
   where m.group_id = t.group_id and m.group_type = t.group_type)

이 솔루션을 사용하면 다음과 같은 이점이 있습니다.

SELECT *
FROM mytable m
WHERE EXISTS (
   SELECT * FROM (
   SELECT "1234-567" group_id, 2 group_type UNION ALL
   SELECT "4321-765", 3 UNION ALL
   SELECT "1111-222", 5) [t]
   WHERE m.group_id = t.group_id AND m.group_type = t.group_type) 

참고로, CTE를 사용하여 내부 테이블을 만들어야 합니다.

아직 본 적은 없지만, 이런 것이 효과가 있을 겁니다.

SELECT * FROM  AgeGroup ag JOIN
(VALUES
('18-24', 18, 24),
('25-34 ', 25, 39),
('35-44 ', 35, 49),
('45-54 ', 45, 59),
('55-64 ', 55, 69),
('65+   ', 65, 299)
) AS x (agegroup, minage, maxage)
ON ag.age_group = x.agegroup 
    AND ag.min_age=x.minage 
    AND ag.max_age=x.maxage

조인을 사용하는 다른 튜플 솔루션은 다음과 같습니다.

SELECT 
  *
FROM mytable m
JOIN
(
   SELECT "1234-567" group_id, 2 group_type 
   UNION ALL SELECT "4321-765", 3 
   UNION ALL SELECT "1111-222", 5
) [t]
ON m.group_id = t.group_id 
AND m.group_type = t.group_type

비슷한 문제가 있었지만 튜플 수집이 동적이었습니다. 쿼리 매개 변수를 통해 SQL Server로 전송되었습니다.저는 다음과 같은 해결책을 생각해냈습니다.

  1. XML로 튜플 전달:

    DECLARE @tuplesXml xml = '<tuples><tuple group-id="1234-567" group-type="2"/><tuple group-id="4321-765" group-type="3"/></tuples>';
    
  2. XML 노드로 필터링할 테이블에 내부 조인:

    SELECT t.* FROM mytable t
    INNER JOIN @tuplesXml.nodes('/tuples/tuple') AS tuple(col)
    ON tuple.col.value('./@group-id', 'varchar(255)') = t.group_id
    AND tuple.col.value('./@group-type', 'integer') = t.group_type
    

질문에 설명된 것보다 조금 더 복잡한 제 상황에서는 잘 작동하는 것 같습니다.

사용할 필요가 있음을 명심하십시오.t.**그리고 테이블이 돌아왔습니다.nodestuple(col)이 경우).

select * from table_name where 1=1 and (column_a, column_b) in ((28,1),(25,1))

언급URL : https://stackoverflow.com/questions/8006901/using-tuples-in-sql-in-clause

반응형