web-dev-qa-db-ja.com

JOIN条件でCASE文を使用できますか?

次の画像は、Microsoft SQL Server 2008 R2システムビューの一部です。画像から、sys.partitionssys.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 '='付近の誤った構文。

this is the image

101
Ogrish Man

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がデータ型の場合、等価性のテストは意味があります。)

182
HABO

代わりに、単純に両方のテーブルにJOINし、SELECT句で、一致するものからデータを返します。

このリンク SQL Serverでの条件付き結合J-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 

編集:コメントに従って。

あなたがしているようにあなたは結合条件を指定することはできません..エラーのない上記のクエリをチェックしてください。共通の列を取り出して、正しい列の値が条件に基づいて評価されます。

29
Niranjan Singh

これを試して:

...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)
16
richardtallent

2つのcase文が必要だと思います。

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ステートメントは2つの値を比較します
  • あなたのCASEステートメントは、CASEステートメントの 内側 を比較していました。 CASEステートメントをSELECTに入れると、CASEステートメントがTrueかFalseかを示すブール値 '1'または '0'が得られると思います。
6
DonkeyKong

これはいいようです

https://bytes.com/topic/sql-server/answers/881862-joining-different-tables-based-condition

FROM YourMainTable
LEFT JOIN AirportCity DepCity ON @TravelType = 'A' and DepFrom =  DepCity.Code
LEFT JOIN AirportCity DepCity ON @TravelType = 'B' and SomeOtherColumn = SomeOtherColumnFromSomeOtherTable
1
user4584103

私はあなたの例を取り、それを編集しました:

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 p.hobt_id 
           WHEN a.type IN (2)
               THEN p.partition_id
           ELSE NULL
           END = a.container_id
1
Gont

ここでは、2つの異なる結果セットの違いを比較しました。これが役に立つかもしれないと思います。

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 
0
Sheikh Kawser

DonkeyKongの例を見てください。

問題は、宣言された変数を使う必要があるということです。これはあなたが比較する必要があるもののあなたの左右を述べることを可能にします。これは、ユーザーの選択に基づいてさまざまなフィールドをリンクする必要があるSSRSレポートをサポートするためのものです。

最初のケースでは、選択に基づいてフィールドの選択を設定してから、結合のために一致させる必要があるフィールドを設定できます。

変数が異なるフィールドから選択する必要がある場合は、右側に2番目のcaseステートメントを追加できます。

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
Kenneth Wilson