상관 관계에 따라 계산 된 열로 선택
-
18-09-2019 - |
문제
나는 많은 SQL을하지 않으며 대부분의 경우 CRUD 작업을하고 있습니다. 때때로 나는 좀 더 복잡한 것을 얻을 것이다. 따라서이 질문은 초보자 질문 일지 모르지만 준비가되었습니다. 나는 방금 몇 시간 동안 이것을 알아 내려고 노력했지만 아무 소용이 없었습니다.
따라서 다음 테이블 구조를 상상해보십시오.
> | ID | Col1 | Col2 | Col3 | .. | Col8 |
ID와 계산 된 열을 선택하고 싶습니다. 계산 된 열에는 0-8 범위가 있으며 쿼리와의 일치 수가 포함되어 있습니다. 또한 특정 수의 일치가있는 행만 포함하도록 결과 세트를 제한하고 싶습니다.
따라서이 샘플 데이터에서 :
> | 1 | 'a' | 'b' | 1 | 2 |
> | 2 | 'b' | 'c' | 1 | 2 |
> | 3 | 'b' | 'c' | 4 | 5 |
> | 4 | 'x' | 'x' | 9 | 9 |
col1 = 'a'또는 col2 = 'c'또는 col3 = 1 또는 col4 = 5에서 계산 된 결과> 1에서 쿼리하고 싶습니다. 결과 세트가 다음과 같습니다.
> | ID | Cal |
> | 1 | 2 |
> | 2 | 2 |
> | 3 | 2 |
중요한 경우 T-SQL 및 SQL Server 2005를 사용하고 있으며 DB 스키마를 변경할 수 없습니다.
또한 하나의 독립적 인 쿼리로 유지하고 저장된 절차 또는 임시 테이블을 만들 필요가 없습니다.
해결책
이 답변은 CTE를 사용하여 파생 된 테이블을 약간 정리하여 SQL 2005와 함께 작동합니다.
WITH Matches AS
(
SELECT ID, CASE WHEN Col1 = 'a' THEN 1 ELSE 0 END +
CASE WHEN Col2 = 'c' THEN 1 ELSE 0 END +
CASE WHEN Col3 = 1 THEN 1 ELSE 0 END +
CASE WHEN Col4 = 5 THEN 1 ELSE 0 END AS Result
FROM Table1
WHERE Col1 = 'a' OR Col2 = 'c' OR Col3 = 1 OR Col4 = 5
)
SELECT ID, Result
FROM Matches
WHERE Result > 1
다른 팁
다음은 부울 비교가 정수 1 또는 0을 반환한다는 사실을 활용하는 솔루션입니다.
SELECT * FROM (
SELECT ID, (Col1='a') + (Col2='c') + (Col3=1) + (Col4=5) AS calculated
FROM MyTable
) q
WHERE calculated > 1;
부울 비교를 괄호로 묶어야합니다. +
보다 우선 순위가 높습니다 =
. 또한 일반적으로 열 별칭을 WHERE
동일한 쿼리 조항.
a를 사용해야하는 것처럼 보일 수 있습니다 WHERE
하위 쿼리의 조항은 행을 제한하지만, 어쨌든 전체 테이블 스캔으로 끝날 것이므로 아마도 큰 승리가 아닙니다. 반면에, 그러한 제한이 매우 하위 쿼리 결과의 행 수를 줄이면 가치가 있습니다.
Quassnoi의 의견, 부울 표현을 정수 값으로 취급 할 수 없다면 부울 조건을 약간 장황하더라도 부울 조건을 정수에 매핑하는 방법이 있어야합니다. 예를 들어:
SELECT * FROM (
SELECT ID,
CASE WHEN Col1='a' THEN 1 ELSE 0 END
+ CASE WHEN Col2='c' THEN 1 ELSE 0 END
+ CASE WHEN Col3=1 THEN 1 ELSE 0 END
+ CASE WHEN Col4=5 THEN 1 ELSE 0 END AS calculated
FROM MyTable
) q
WHERE calculated > 1;
이 쿼리는 인덱스 친화적입니다.
SELECT id, SUM(match)
FROM (
SELECT id, 1 AS match
FROM mytable
WHERE col1 = 'a'
UNION ALL
SELECT id, 1 AS match
FROM mytable
WHERE col2 = 'c'
UNION ALL
SELECT id, 1 AS match
FROM mytable
WHERE col3 = 1
UNION ALL
SELECT id, 1 AS match
FROM mytable
WHERE col4 = 5
) q
GROUP BY
id
HAVING SUM(match) > 1
이것은 단지 효율적입니다 모두 당신이 검색하는 열은 먼저 색인화되었으며, 둘째는 높은 카디널리티 (많은 뚜렷한 값)를 가지고 있습니다.
성능 세부 정보는 내 블로그 에서이 기사를 참조하십시오.