【问题标题】:SQL Server : conditional (IF-ELSE) on Left Outer JoinSQL Server:左外连接上的条件(IF-ELSE)
【发布时间】:2017-03-28 13:49:24
【问题描述】:

我有一个场景,我想在一个连接上设置一个条件,即如果 A = B 然后加入 1 个集合,否则加入另一个集合。两种情况下的表格都是相同的,只是条件不同。我尝试过使用大小写,但出现语法错误。

SELECT * 
FROM [Table1] CUP
LEFT OUTER JOIN Table2 CP ON CUP.StateCode = CP.StateCode 
                          AND (CUP.ClientId = CP.ClientId OR CP.ClientId = 0)

我尝试过的

SELECT * 
FROM [Table1] CUP
LEFT OUTER JOIN Table2 CP
          ON CASE
                WHEN CUP.ClientId =  CP.ClientId 
                   THEN CUP.StateCode = CP.StateCode AND CUP.ClientId =  CP.ClientId
                   ELSE CUP.StateCode = CP.StateCode AND (CUP.ClientId <>  CP.ClientId or CP.ClientId = 0)

@juan

 ON 
   CUP.StateCode = CP.StateCode AND ((CUP.ClientId =  CP.ClientId or CP.ClientId <> 0) OR (CUP.ClientId <> CP.ClientId or CP.ClientId = 0))

【问题讨论】:

  • 实际上在第 1 部分中,我的匹配 clientid 和 0 的代码数据即将到来。我只想要其中一个
  • ... ON (A=B AND 1) OR (A B AND another) ... 基于您的模棱两可的描述。这应该工作
  • 在 ON 和 WHERE 子句中使用 AND/OR 而不是大小写通常要好得多。
  • 您发布的第一个查询有什么问题?这应该是这样写的,并且在语法上是正确的,即使你说你遇到了语法错误。
  • 那是因为你的case expressxion无效。正如我之前所说,它不能用于这样的多个谓词。

标签: sql sql-server join left-join


【解决方案1】:
  • 您必须将coalesce 用于SELECT 子句
  • 注意CP1.ClientId is null,它消除了 Gordon 解决方案对 NULLS 的限制

select  ...

from                    table1  CUP

        left outer join Table2  CP1

        on              CP1.StateCode = CUP.StateCode  
                    and CP1.ClientId  = CUP.ClientId 

        left outer join Table2  CP2

        on              CP1.ClientId is null

                    and CP2.StateCode = CUP.StateCode 
                    and CP2.ClientId  = 0

【讨论】:

  • 这是一个非此即彼的条件,我只希望来自一个连接的数据第二个连接应该返回 null...目前我从每个表中获得 20 行,10 行。第二个表包含匹配以及0。如果找到匹配忽略零
  • 我不明白你的解释。如果 1st JOIN 找到与 2nd JOIN 匹配的匹配项,则无法根据定义找到匹配项。附:如果您只发布数据样本 + 所需结果,那么 IT 对每个人来说都会容易得多。
【解决方案2】:

我想你想要两个left join,一个用于第一个值,第二个用于默认值:

SELECT CUP.*, COALESCE(CP.col1, CPdef.col1) as col1, . . .
FROM [Table1] CUP LEFT OUTER JOIN
     Table2 CP
     ON CUP.StateCode = CP.StateCode AND CUP.ClientId = CP.ClientId LEFT OUTER JOIN
     Table2 CdPef
     ON CUP.StateCode = CPdef .StateCodeCP AND CPdef.ClientId = 0;

请注意,COALESCE() 假定您关心的列自然不是NULL

如果您只想要一个匹配项,另一种方法是outer apply

SELECT CUP.*, cp.*
FROM [Table1] CUP OUTER APPLY
     (SELECT top 1 cp.*
      FROM Table2 Cp
      WHERE CUP.StateCode = CP.StateCode AND
            (CUP.ClientId = CP.ClientId OR CP.ClientId = 0)
      ORDER BY CP.ClientId DESC  -- assumes `CP.ClientId` is not null
     ) cp;

实际上,您可以使用TOP (1) WITH TIES 来获得多个匹配项。所以这不仅限于单个匹配行。

【讨论】:

    【解决方案3】:

    当一个案例说完了,它以一个值结束。

    case when SomeColumn = 4 then 1 end
    

    如您所见,返回值为 VALUE

    您可以使用它在连接中返回列,但实际上您正在返回列中的值

    select aa.a
    from aa
    inner join bb
    on aa.a = case when bb.a is null then 4 else bb.a end
    

    您不能使用大小写来返回表达式

    case when aa.a = 4 then (aa.a = bb.a) end -- this is gonna fail
    

    在这些情况下使用 OR:

    SELECT * 
    FROM [Table1] CUP
    LEFT OUTER JOIN Table2 CP
      ON (CUP.ClientId =  CP.ClientId 
          and CUP.StateCode = CP.StateCode )
      or (CUP.StateCode = CP.StateCode 
          AND (CUP.ClientId <>  CP.ClientId 
          or CP.ClientId = 0))
    

    【讨论】:

      【解决方案4】:

      我写了这个:

      SELECT * 
        FROM   TABLE1 CUP
        INNER JOIN TABLE2 CP ON CUP.StateCode = CP.StateCode 
         AND CUP.ClientId =  CP.ClientId   
        UNION ALL
        SELECT * 
        FROM (SELECT * FROM TABLE1 WHERE NOT EXISTS (SELECT 1 FROM TABLE2 WHERE TABLE2.CLIENTID = TABLE1.CLIENTID) ) CUP 
        INNER JOIN TABLE2 CP  ON    CUP.StateCode = CP.StateCode AND CP.CLIENTID=0
      

      我用这个数据试了一下:

      CREATE TABLE TABLE1  (STATECODE INT, CLIENTID INT);
      CREATE TABLE TABLE2  (STATECODE INT, CLIENTID INT);
      INSERT INTO TABLE1 VALUES (1,100);
      INSERT INTO TABLE1 VALUES (1,200);
      INSERT INTO TABLE1 VALUES (4,300);
      INSERT INTO TABLE1 VALUES (5,400);
      INSERT INTO TABLE1 VALUES (4,500);
      
      INSERT INTO TABLE2 VALUES (1,100);
      INSERT INTO TABLE2 VALUES (1,200);
      INSERT INTO TABLE2 VALUES (4,0);
      INSERT INTO TABLE2 VALUES (5,0);
      

      输出:

      STATECODE   CLIENTID    STATECODE   CLIENTID
      ----------- ----------- ----------- -----------
      1           100         1           100
      1           200         1           200
      4           300         4           0
      5           400         5           0
      4           500         4           0
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多