【问题标题】:SQL LEFT JOIN with conditional CASE statements带有条件 CASE 语句的 SQL LEFT JOIN
【发布时间】:2016-01-11 07:24:58
【问题描述】:

希望这是一个快速的

SELECT *
FROM T
left JOIN J ON 
  CASE
    WHEN condition1 THEN 1 --prefer this option even if CASE2 has a value
    WHEN condition2 THEN 2
    ELSE 0
  END = 1 (edit: but if 1 does not satisfy, then join on 2)

两种情况都返回结果,但我希望 THEN 1 取代 THEN 2 并成为查找优先级

我可以让 SQL 执行诸如加入 max(CASE) 之类的操作吗?

基本上我试图从 Excel 复制嵌套的 INDEX/MATCH

编辑:我听到的是,案例应该在第一个返回的 TRUE 处停止,但是当我测试时它的行为不是那样

SELECT *
FROM T
left JOIN J ON 
  CASE
    WHEN condition1 THEN 1 --prefer this option even if CASE2 has a value
    WHEN condition2 THEN 1
    ELSE 0
  END = 1

它似乎有时更喜欢 2nd THEN 1,但并非总是如此……有什么我遗漏的东西会导致这种行为吗?

【问题讨论】:

  • 案例表达式,而不是案例陈述......
  • 将使用第一个真正的条件。
  • 我认为第一个 TRUE 也会被使用,但是当我测试它时,情况并非如此。 (当我测试它时,两者都是 THEN 1)我为这个例子添加了 THEN 2
  • 该语句不会捕获 col2 匹配而 col1 不匹配的情况。请添加数据示例以及预期的结果集。
  • 也许您的联接只需要使用OR,但您输出的列描述了按优先级应用的匹配项。

标签: sql sql-server tsql join case


【解决方案1】:

哪个条件导致行在连接中匹配并不重要。在连接中使用case 表达式是有正当理由的,但我认为您只想or 您的条件,然后使用case 表达式输出匹配的排名原因。

SELECT *, CASE WHEN <condition1> THEN 1 WHEN <condition2> THEN 2 END as match_code
FROM T LEFT OUTER JOIN J ON <condition1> or <condition2>

关于 Excel 中的“嵌套索引/匹配”,我不知道该怎么做。如果我在上面的错误轨道上,那么也许您正在寻找嵌套的 case 表达式?

现在,如果您的条件将在不同的行中匹配并且您只想保留一个,那么...

WITH matches AS (
    SELECT *, CASE WHEN <condition1> THEN 1 WHEN <condition2> THEN 2 END AS match_code
    FROM T LEFT OUTER JOIN J ON <condition1> OR <condition2>
), ranked as (
    SELECT *, MIN(match_code) OVER (PARTITION BY ???) AS keeper
    FROM matches
)
SELECT ...
FROM ranked
WHERE match_code = keeper

【讨论】:

  • 我认为这是最好的方法。选择 CASE 和 CTE
【解决方案2】:

好吧,你的 CASE 语句中总是可以有几个条件:

  SELECT *
FROM T

left JOIN J ON 
  CASE
    WHEN condition1 THEN 1 --prefer this option even if CASE2 has a value
    WHEN condition2 And !condition1 THEN 2
  ELSE 0
END = 1

--已更新-- 如果您的两个条件都需要匹配,但条件 1 是可选的,那么您也可以尝试以下语句:

  SELECT *
FROM T  
left JOIN J ON 
  CASE
    WHEN condition1 And condition2 THEN 1 --Both conditions match
    WHEN condition2 THEN 2 -- condition1 has no match
  ELSE 0
END = 1

【讨论】:

  • 但正如@Amir 在他的评论中回答的那样,如果条件 1 匹配,那么 SQL Server 将不匹配任何其他条件,并且会通过选择第一个选项来停止。
  • 我想我想做的是告诉 SQL 我想在两种情况下都尝试 JOIN 但返回结果为 1,如果 1 没有结果,则转到 2
  • 嗯,实际上就是这样! :) 看看:msdn.microsoft.com/en-us/library/ms181765.aspx - CASE 语句按顺序评估其条件,并在满足条件的第一个条件处停止。
  • 所以如果.. 我设置了两个条件 THEN 1.. 它应该在第一个满足的条件处停止,而不是进一步进入 CASE.. 对吗?
  • 看,你有两个 WHEN 选项的 CASE,不管有多少条件。对于指定的所有条件都匹配的任何 WHEN,处理该 WHEN 并且 SQL Server 将停止进一步处理。如果不存在所有条件都匹配的 WHEN 条件,则服务器使用 ELSE 语句进行处理。如果没有 ELSE 语句,则最终值为 NULL。
【解决方案3】:

您可以分两步使用With 声明:

 With first_join as  
    (SELECT *
    FROM T
    left JOIN J ON condition1)
      select * from first_join 
    join J On case when Name_of_2nd_condition is null 
       then     condition2 
      ELSE null end

【讨论】:

    【解决方案4】:

    您可以使用 CROSS APPLY /OUTER APPLY 运算符:https://www.mssqltips.com/sqlservertip/1958/sql-server-cross-apply-and-outer-apply/

    SELECT *
    FROM T
        OUTER APPLY (SELECT TOP 1 *
                     FROM J
                     WHERE condition1 OR condition2
                     ORDER BY order) J
    

    【讨论】:

    • 这种工作方式是一种变通方法。不是我要找的
    • 通过这种方式,您可能会提高您的表现,但我同意,这是一种解决方法。
    • 。看起来我可以按结果集对其进行排序,但我无法告诉它更喜欢哪个条件
    • 您也可以在 SELECT 语句中创建 CASE WHEN。让我知道条件,使查询更相关
    • 这里是实际代码如果有帮助的话,我不知道如何在评论区格式化left JOIN [CC_Note_Log].[dbo].[Desk_Mapping] DON CASE WHEN S.tag1=D.Location and S.tag5=D.Line THEN 1WHEN S.Location2ID=D.TwoID and S.tag5=D.Line THEN 1WHEN S.tag1='LKW' and S.tag5=D.Line THEN 1ELSE 0@ 987654330@
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多