JOIN 조건에서 CASE 문을 사용할 수 있습니까?


141

다음 이미지는 Microsoft SQL Server 2008 R2 시스템 뷰의 일부입니다. 이미지에서 sys.partitions와 의 관계는 sys.allocation_units의 값에 따라 달라집니다 sys.allocation_units.type. 그래서 그것들을 합치려면 다음과 비슷한 것을 쓰십시오.

SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id = p.hobt_id 
               WHEN a.type IN (2)
                   THEN a.container_id = p.partition_id
               END 

그러나 위 코드는 구문 오류를 발생시킵니다. 나는 그것이 CASE성명서 때문이라고 생각합니다 . 누구든지 조금 설명하는 데 도움이 될 수 있습니까?


오류 메시지 추가 :

메시지 102, 수준 15, 상태 1, 줄 6 '='근처의 구문이 잘못되었습니다.

이것은 이미지입니다


36
이 아름다운 DB 다이어그램을 만들기 위해 어떤 소프트웨어를 사용하셨습니까?
LearnByReading

2
@LearnByReading 어떤 소프트웨어가 사용되었는지 확인한 적이 있습니까?
632716

1
@ User632716 안타깝게도 아닙니다!
LearnByReading

2
@ User632716 실제로 MySQL Workbench라고 생각합니다. 그러나 나는 응답을받지 못했습니다
LearnByReading

@LearnByReading 모르겠습니다. Microsoft에서 제공합니다.
단지 학습자

답변:


223

CASE표현식의 값 리턴 THEN절의 부. 따라서 다음과 같이 사용할 수 있습니다.

SELECT  * 
FROM    sys.indexes i 
    JOIN sys.partitions p 
        ON i.index_id = p.index_id  
    JOIN sys.allocation_units a 
        ON CASE 
           WHEN a.type IN (1, 3) AND a.container_id = p.hobt_id THEN 1
           WHEN a.type IN (2) AND a.container_id = p.partition_id THEN 1
           ELSE 0
           END = 1

리턴 값으로 무언가를 수행해야합니다 (예 : 1과 비교). 명령문이 지정 값을 리턴하거나 동등성에 대해 테스트하려고했으나 CASE/ THEN절의 컨텍스트에서 의미가 없습니다 . ( BOOLEAN데이터 유형 인 경우 동등성 테스트가 적합합니다.)


@ HABO 덕분에 저에게 도움이되었습니다 ...하지만 문제는이 작업을 수행 할 때 조건이 무너지는 것입니다 ... 어떻게 깨뜨릴 수 있는지 알려주십시오.
Sagar Tandel

1
@SagarTandel-죄송합니다, "넘어지다"와 "어떻게 깰까요"를 이해하지 못합니다. 당신의 의견을 명확히 할 수 있습니까? (최근에 Saba에서 다이빙을 시작했습니다. Nitrox 일 수 있습니다.)
HABO

내가 원하지 않는 모든 조건을 확인합니다. 조건과 일치하면 사례를 종료하고 싶습니다.
Sagar Tandel

3
@SagarTandel- MSDN에서 : "CASE 문은 조건을 순차적으로 평가하고 조건이 만족되는 첫 번째 조건으로 중지합니다." 명시 적으로 명시된 조건과 일치하지 않는 모든 조인 된 행을 원하면 꼬리 끝을에서 = 1로 변경하십시오 = 0. 그러나 결과가 마음에 들지 않을 것이라고 생각합니다.
HABO

sys.allocation_units a.type IN (1, 3) 및 a.container_id = p.hobt_id 그때 1 a.type IN (2) AND a.container_id = p.partition_id THEN 1 ELSE 0 END = 1 인 경우 ON CASE 솔루션 위의 엔티티 프레임 워크에서이를 작성할 수 있습니까
r.hamd

36

대신 두 테이블 모두에 조인하고 SELECT 절에서 다음과 일치하는 데이터를 반환합니다.

이 링크 를 SQL Server의 조건부 조인JOIN ON 절의 T-SQL 사례 설명 링크로 이동하는 것이 좋습니다.

예 :

    SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON a.container_id =
            CASE
               WHEN a.type IN (1, 3)
                   THEN  p.hobt_id 
               WHEN a.type IN (2)
                   THEN p.partition_id
               END 

편집 : 의견에 따라.

수행중인 조인 조건을 지정할 수 없습니다. 오류가없는 위의 쿼리를 확인하십시오. 공통 열을 꺼내고 오른쪽 열 값이 조건에 따라 평가됩니다.


1
무슨 conditional join뜻입니까? 각 조인 (교차 제외)은 조건부입니다. 이 사례는 다른 사례와 어떻게 다릅니 까? 샘플에 조건이있는 내부 조인이 있고 OP 쿼리에 조건이있는 조인이 있습니다.
zerkms

@ zerkms : 나는 혼란스러워 들린다. 나는, 생각 조건 가입 이 상황은 누구의 조건이 다른 조건에 따라 가입 의미에서.
Andriy M

@Andriy M : 사소한 조건에 대한 다른 용어를 생각할 이유가 OR있습니까?
zerkms

@zerkms : 어, 그렇습니다. 혼란 스럽기 때문입니다. :) 그러나 나는 당신 이 다른 용어를 생각 하지 않는 어떤 이유가 있었는지 묻기를 의미한다고 생각합니다 .이 경우 나는 확신 할 수 없습니다. 당신이 이유를 묻는다면 글쎄, 나는 단지 충분히 귀찮게 할 수 없다고 생각합니다. :) 대체 조건과조인은 어떻습니까? 용어를 잘 작성하지 못하는 것이 두렵습니다. 그러나 개념적으로는 "condition with OR"가 아니라 "conditional condition"에 관한 것 입니다. 사용 OR은 그것을 구현하는 한 가지 방법 일뿐입니다.
Andriy M

@Andriy M : 알겠습니다. 그러나 개인적으로 나는 여전히 1 과 2 또는 1로 사소한 조건 의 이름을 밝힐 이유를 알지 못합니다 . 다른 쿼리와 다른 것은 없습니다. ORANDsCASE
zerkms

17

이 시도:

...JOIN sys.allocation_units a ON 
  (a.type=2 AND a.container_id = p.partition_id)
  OR (a.type IN (1, 3) AND a.container_id = p.hobt_id)

작동하지만 질문의 쿼리는 완벽하게 유효합니다. 따라서 여전히 OP 코드에 어떤 문제가 있는지 설명하지 않습니다
zerkms

10

두 가지 사례 진술이 필요하다고 생각합니다.

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON 
        -- left side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id
               WHEN a.type IN (2)
                   THEN a.container_id
            END 
        = 
        -- right side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN p.hobt_id
               WHEN a.type IN (2)
                   THEN p.partition_id
            END             

이 때문입니다:

  • CASE 문은 END에서 단일 값을 리턴합니다.
  • ON 문은 두 값을 비교합니다
  • CASE 문이 CASE 문 내부 에서 비교를 수행했습니다 . CASE 문을 SELECT에 넣으면 CASE 문이 True 또는 False로 평가되는지 여부를 나타내는 부울 '1'또는 '0'이 나타납니다.

5

나는 당신의 예를 들어서 편집했습니다.

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON a.container_id = (CASE
           WHEN a.type IN (1, 3)
               THEN p.hobt_id 
           WHEN a.type IN (2)
               THEN p.partition_id
           ELSE NULL
           END)


1

그래 넌 할수있어. 다음은 예입니다.

SELECT a.*
FROM TableA a
LEFT OUTER JOIN TableB j1 ON  (CASE WHEN LEN(COALESCE(a.NoBatiment, '')) = 3 
                                THEN RTRIM(a.NoBatiment) + '0' 
                                ELSE a.NoBatiment END ) = j1.ColumnName 

1
이 코드가 문제를 해결하는 방법과 이유에 대한 설명포함 하여 질문을 해결할 수는 있지만 게시물의 품질을 향상시키는 데 도움이되고 더 많은 투표를 할 수 있습니다. 지금 질문하는 사람이 아니라 독자들에게 질문에 대답하고 있음을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
이중 신호음

0

동키 콩의 예를 들었습니다.

문제는 선언 된 변수를 사용해야합니다. 이를 통해 비교해야 할 내용의 왼쪽과 오른쪽을 지정할 수 있습니다. 사용자의 선택에 따라 다른 필드를 연결해야하는 SSRS 보고서를 지원하기위한 것입니다.

초기 사례는 선택을 기반으로 필드 선택을 설정 한 다음 조인을 위해 일치시켜야하는 필드를 설정할 수 있습니다.

변수가 다른 필드에서 선택해야하는 경우 오른쪽에 두 번째 사례 설명을 추가 할 수 있습니다.

LEFT OUTER JOIN Dashboard_Group_Level_Matching ON
       case
         when @Level  = 'lvl1' then  cw.Lvl1
         when @Level  = 'lvl2' then  cw.Lvl2
         when @Level  = 'lvl3' then  cw.Lvl3
       end
    = Dashboard_Group_Level_Matching.Dashboard_Level_Name

0

다음은 두 가지 결과 집합의 차이점을 비교 한 것입니다.

SELECT main.ColumnName, compare.Value PreviousValue,  main.Value CurrentValue
FROM 
(
    SELECT 'Name' AS ColumnName, 'John' as Value UNION ALL
    SELECT 'UserName' AS ColumnName, 'jh001' as Value UNION ALL
    SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
    SELECT 'Phone' AS ColumnName, NULL as Value UNION ALL
    SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
    SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
    SELECT 'IsActive' AS ColumnName, '1' as Value
) main
INNER JOIN
(
    SELECT 'Name' AS ColumnName, 'Rahul' as Value UNION ALL
    SELECT 'UserName' AS ColumnName, 'rh001' as Value UNION ALL
    SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
    SELECT 'Phone' AS ColumnName, '01722112233' as Value UNION ALL
    SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
    SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
    SELECT 'IsActive' AS ColumnName, '1' as Value
) compare
ON main.ColumnName = compare.ColumnName AND
CASE 
    WHEN main.Value IS NULL AND compare.Value IS NULL THEN 0
    WHEN main.Value IS NULL AND compare.Value IS NOT NULL THEN 1
    WHEN main.Value IS NOT NULL AND compare.Value IS NULL THEN 1
    WHEN main.Value <> compare.Value THEN 1
END = 1 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.