SQL WHERE...IN 절 다중 열
SQL Server에 다음 쿼리를 구현해야 합니다.
select *
from table1
WHERE (CM_PLAN_ID,Individual_ID)
IN
(
Select CM_PLAN_ID, Individual_ID
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
)
하지만 WHERE는..IN 절은 열을 하나만 허용합니다.두 개 이상의 열을 다른 내부 SELECT와 비교하려면 어떻게 해야 합니까?
대신 WHERE EXISTES 구문을 사용해야 합니다.
SELECT *
FROM table1
WHERE EXISTS (SELECT *
FROM table2
WHERE Lead_Key = @Lead_Key
AND table1.CM_PLAN_ID = table2.CM_PLAN_ID
AND table1.Individual_ID = table2.Individual_ID)
서브쿼리에서 파생테이블을 생성하여 table1을 다음 파생테이블에 결합할 수 있습니다.
select * from table1 LEFT JOIN
(
Select CM_PLAN_ID, Individual_ID
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
) table2
ON
table1.CM_PLAN_ID=table2.CM_PLAN_ID
AND table1.Individual=table2.Individual
WHERE table2.CM_PLAN_ID IS NOT NULL
솔루션에 대한 경고:
행이 고유하지 않으면 많은 기존 솔루션이 잘못된 출력을 제공합니다.
테이블을 작성하는 유일한 사용자일 경우, 이것은 관련이 없을 수 있지만 테이블 중 하나에 고유한 행이 포함되지 않을 수 있는 경우 여러 솔루션이 해당 코드와 다른 수의 출력 행을 제공합니다.
문제 설명에 대한 경고:
여러 개의 열이 존재하지 않는 경우 무엇을 원하는지 신중하게 고려하십시오.
2개의 컬럼이 있는 in을 보면 다음 2개의 의미를 알 수 있습니다.
- 열 a와 열 b의 값은 다른 표에서 독립적으로 표시됩니다.
- 열 a와 열 b의 값이 다른 테이블에 같은 행에 함께 표시됩니다.
시나리오 1은 매우 사소한 것입니다.단순히 2개의 IN 문을 사용합니다.
대부분의 기존 답변에 따라 시나리오 2에 대한 언급 및 추가 접근법의 개요(및 간단한 판단)를 제공한다.
EXISTES(안전, SQL Server 권장)
@mrdenny에서 제공하는 바와 같이, EXISTS는 당신이 찾고 있는 것과 정확히 일치합니다.이 예는 다음과 같습니다.
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
LEFT SEMI JOIN(안전, 이를 지원하는 방언에 권장)
이 방법은 매우 간결하지만 SQL Server를 포함한 대부분의 SQL 방언은 현재 지원하지 않습니다.
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
다중 IN 문(안전하지만 코드 중복에 주의)
@cataclysm에서 언급한 바와 같이 2개의 IN 문을 사용하는 것도 효과적인 방법입니다.아마 다른 솔루션보다 성능이 뛰어날 수도 있습니다.단, 매우 주의해야 할 것은 코드 복제입니다.다른 테이블에서 선택하거나 where 문을 변경할 경우 논리 불일치가 발생할 위험이 높아집니다.
기본 솔루션
SELECT * from T1
WHERE a IN (SELECT a FROM T2 WHERE something)
AND b IN (SELECT b FROM T2 WHERE something)
코드 중복이 없는 솔루션(일반 SQL Server 쿼리에서 작동하지 않을 수 있음)
WITH mytmp AS (SELECT a, b FROM T2 WHERE something);
SELECT * from T1
WHERE a IN (SELECT a FROM mytmp)
AND b IN (SELECT b FROM mytmp)
INSER JOIN(기술적으로는 안전할 수 있지만 대부분의 경우 그렇지 않음)
필터로서 내부 조인 사용을 권장하지 않는 이유는 실제로는 오른쪽 테이블의 중복으로 인해 왼쪽 테이블의 중복이 발생하는 경우가 많기 때문입니다.그리고 설상가상으로 최종 결과를 명확하게 할 수 있지만, 실제로는 왼쪽 표가 고유할 필요가 없을 수도 있습니다(또는 선택한 열에서 고유하지 않을 수도 있습니다.또한 왼쪽 테이블에 존재하지 않는 열을 실제로 선택할 수 있습니다.
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
가장 흔한 실수:
- 안전한 서브쿼리 없이 T2에 직접 접속합니다.중복의 위험이 있다)
- SELECT * (T2에서 열을 가져오기 위해 구아레인화됨)
- SELECT c(열은 항상 T1에서 오는 것을 보증하지 않습니다)
- 잘못된 위치에 구별되거나 구별되지 않음
컬럼과 분리기 연결(안전하지 않은, 끔찍한 성능)
기능적 문제는 열에 발생할 수 있는 구분 기호를 사용하면 결과가 100% 정확하도록 하는 것이 까다롭다는 것입니다.기술적인 문제는 이 방법이 종종 유형 변환을 유발하고 인덱스를 완전히 무시하기 때문에 성능이 저하될 수 있다는 것입니다.이러한 문제에도 불구하고 소규모 데이터셋의 임시 쿼리에 여전히 이 기능을 사용하고 있다는 것을 인정해야 합니다.
SELECT * FROM T1
WHERE CONCAT(a,"_",b) IN
(SELECT CONCAT(a,"_",b) FROM T2)
열이 숫자일 경우 일부 SQL 방언에서는 먼저 열을 문자열로 캐스트해야 합니다.SQL Server가 자동으로 이 작업을 수행할 것이라고 생각합니다.
정리하면: SQL에서 이 작업을 수행하는 방법은 여러 가지가 있습니다.안전한 선택을 하면 놀라움을 피할 수 있고 장기적으로 시간과 헤드스케이스를 절약할 수 있습니다.
select * from tab1 where (col1,col2) in (select col1,col2 from tab2)
Oracle은 선택한 열 중 하나 이상이 NULL인 행을 무시합니다. 이 경우 NVL-Funktion을 사용하여 NULL을 특별한 값(값에는 포함되지 않아야 함)에 매핑할 수 있습니다.
select * from tab1
where (col1, NVL(col2, '---') in (select col1, NVL(col2, '---') from tab2)
단순 EXISTS 절이 가장 깨끗합니다.
select *
from table1 t1
WHERE
EXISTS
(
Select * --or 1. No difference...
From CRM_VCM_CURRENT_LEAD_STATUS Ex
Where Lead_Key = :_Lead_Key
-- correlation here...
AND
t1.CM_PLAN_ID = Ex.CM_PLAN_ID AND t1.CM_PLAN_ID = Ex.Individual_ID
)
상관관계에 여러 행이 있는 경우 JOIN은 출력에 여러 행을 제공하기 때문에 구별이 필요합니다.그 때문에, 통상, EXIST가 보다 효율이 향상됩니다.
: ★SELECT *
하면 행 의 OIN을 사용하면 행 제한 테이블의 열도 포함됩니다.
일반 내부 조인만 수행할 수 있는데 WHERE EXISTS 또는 DERVENED TABles를 사용하는 이유는 무엇입니까?
SELECT t.*
FROM table1 t
INNER JOIN CRM_VCM_CURRENT_LEAD_STATUS s
ON t.CM_PLAN_ID = s.CM_PLAN_ID
AND t.Individual_ID = s.Individual_ID
WHERE s.Lead_Key = :_Lead_Key
(CM_PLAN_ID, Individual_)의 쌍인 경우ID)는 상태 테이블에서 고유하지 않습니다.대신 SELECT DISTINCT t.*가 필요할 수 있습니다.
Postgres SQL : version 9.6
Total records on tables : mjr_agent = 145, mjr_transaction_item = 91800
1. 와의 사용EXISTS
[평균 쿼리 시간 : 1.42초]
SELECT count(txi.id)
FROM
mjr_transaction_item txi
WHERE
EXISTS ( SELECT 1 FROM mjr_agent agnt WHERE agnt.agent_group = 0 AND (txi.src_id = agnt.code OR txi.dest_id = agnt.code) )
2. 2줄로 사용IN
조항 [평균 쿼리 시간: 0.37초]
SELECT count(txi.id) FROM mjr_transaction_item txi
WHERE
txi.src_id IN ( SELECT agnt.code FROM mjr_agent agnt WHERE agnt.agent_group = 0 )
OR txi.dest_id IN ( SELECT agnt.code FROM mjr_agent agnt WHERE agnt.agent_group = 0 )
3. 와의 사용INNNER JOIN
패턴 [평균 쿼리 시간: 2.9초]
SELECT count(DISTINCT(txi.id)) FROM mjr_transaction_item txi
INNER JOIN mjr_agent agnt ON agnt.code = txi.src_id OR agnt.code = txi.dest_id
WHERE
agnt.agent_group = 0
그래서 두 번째 옵션을 선택했습니다.
*** T-SQL ***
값싼 해킹으로 string_agg를 사용하여 값싼 정규화를 얻었어요.(멀티플렉스입니다.너무 힘들다는 거 알아요.80년대 스타일의 상자 그림으로 당신의 고통을 보상해 드렸습니다.즐겨보세요!~)
여기 샘플이 있습니다(이름 치환에 재미를 느꼈습니다:D)
select
vendorId,
affiliate_type_code,
parent_vendor_id,
state_abbr,
county_abbr,
litigation_activity_indicator,
string_agg(employee_id,',') as employee_ids,
string_agg(employee_in_deep_doodoo,',') as 'employee-inventory connections'
from (
select distinct top 10000 -- so I could pre-order my employee id's - didn't want mixed sorting in those concats
mi.missing_invintory_identifier as rqid,
vendorId,
affiliate_type_code,
parent_vendor_id,
state_abbr,
county_abbr,
litigation_activity_indicator,
employee_identifier as employee_id,
concat(employee_identifier,'-',mi.missing_invintory_identifier) as employee_in_deep_doodoo
from
missing_invintory as mi
inner join vendor_employee_view as ev
on mi.missing_invintory_identifier = ev.missing_invintory_identifier
where ev.litigation_activity_indicator = 'N'
order by employee_identifier desc
) as x
group by
vendorId,
affiliate_type_code,
parent_vendor_id,
state_abbr,
county_abbr,
litigation_activity_indicator
having count(employee_id) > 1
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ vendorId ┃ affiliate_type ┃ parent_vendor_id ┃ state_abbr ┃ county_abbr ┃ litigation_indicator ┃ employee_ids ┃ employee-inventory connections ┃
┣━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ 123 ┃ EXP ┃ 17 ┃ CA ┃ SDG ┃ N ┃ 112358,445678 ┃ 112358-1212,1534490-1212 ┃
┣━━━━━━━━━━╋━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ 4567 ┃ PRI ┃ 202 ┃ TX ┃ STB ┃ Y ┃ 998754,332165 ┃ 998754-4545,332165-4545 ┃
┗━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
쿼리:
select ord_num, agent_code, ord_date, ord_amount
from orders
where (agent_code, ord_amount) IN
(SELECT agent_code, MIN(ord_amount)
FROM orders
GROUP BY agent_code);
위의 쿼리는 mysql에서 동작했습니다.다음 링크를 참조해 주세요. -- >
https://www.w3resource.com/sql/subqueries/multiplee-row-column-subqueries.php
어떤 형태로든 열을 연결하는 것은 "해킹"이지만 제품이 두 개 이상의 열에 대한 세미 조인 기능을 지원하지 않는 경우 어쩔 수 없는 경우가 있습니다.
내부/외부 결합 솔루션이 작동하지 않는 예:
select * from T1
where <boolean expression>
and (<boolean expression> OR (ColA, ColB) in (select A, B ...))
and <boolean expression>
...
쿼리가 단순하지 않은 경우 정기적인 내부/외부 조인을 수행하기 위해 기본 테이블 세트에 액세스할 수 없는 경우가 있습니다.
이 "해크"를 사용하는 경우 필드를 결합할 때 필드 사이에 딜리미터를 충분히 추가하여 다음과 같이 오역하지 않도록 하십시오.ColA + ":-:" + ColB
테이블 하나를 원하는 경우 다음 쿼리를 사용합니다.
SELECT S.*
FROM Student_info S
INNER JOIN Student_info UT
ON S.id = UT.id
AND S.studentName = UT.studentName
where S.id in (1,2) and S.studentName in ('a','b')
및 표 데이터는 다음과 같습니다.
id|name|adde|city
1 a ad ca
2 b bd bd
3 a ad ad
4 b bd bd
5 c cd cd
다음으로 다음과 같이 출력합니다.
id|name|adde|city
1 a ad ca
2 b bd bd
우리는 간단히 이것을 할 수 있다.
select *
from
table1 t, CRM_VCM_CURRENT_LEAD_STATUS c
WHERE t.CM_PLAN_ID = c.CRM_VCM_CURRENT_LEAD_STATUS
and t.Individual_ID = c.Individual_ID
이렇게 하면 쉽게 찾을 수 있었다.
Select *
from table1
WHERE (convert(VARCHAR,CM_PLAN_ID) + convert(VARCHAR,Individual_ID))
IN
(
Select convert(VARCHAR,CM_PLAN_ID) + convert(VARCHAR,Individual_ID)
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
)
이것이 도움이 되기를 바랍니다:)
단순하고 잘못된 방법은 +를 사용하여 두 열을 결합하거나 연결해서 하나의 열을 만드는 것입니다.
Select *
from XX
where col1+col2 in (Select col1+col2 from YY)
물론 이건 꽤 느릴 거야.프로그래밍에서는 사용할 수 없지만, 단지 무언가를 사용할 수 있는지 확인하기 위해 쿼리하는 경우입니다.
언급URL : https://stackoverflow.com/questions/1136380/sql-where-in-clause-multiple-columns
'prosource' 카테고리의 다른 글
SQL "between" (사이에 포함되지 않음) (0) | 2023.04.08 |
---|---|
SQL의 여러 열 업데이트 (0) | 2023.04.08 |
Powershell - Invoke-WebRequest 사용이 브라우저 다운로드보다 느린 이유는 무엇입니까? (0) | 2023.04.08 |
명령줄 인수를 PowerShell ps1 파일에 전달하는 방법 (0) | 2023.04.08 |
Maven 클린 설치: 목표 org.apache.maven을 실행하지 못했습니다.플러그인: maven-displicate-displicate: 3.2.0: 개요 (0) | 2023.04.03 |