带有条件 CASE 语句的 SQL LEFT JOIN
Posted
技术标签:
【中文标题】带有条件 CASE 语句的 SQL LEFT JOIN【英文标题】:SQL LEFT JOIN with conditional CASE statements 【发布时间】: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
,但您输出的列描述了按优先级应用的匹配项。
【参考方案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] D
ON
CASE
WHEN S.tag1=D.Location and S.tag5=D.Line THEN 1
WHEN S.Location2ID=D.TwoID and S.tag5=D.Line THEN 1
WHEN S.tag1='LKW' and S.tag5=D.Line THEN 1
ELSE 0
@ 987654330@以上是关于带有条件 CASE 语句的 SQL LEFT JOIN的主要内容,如果未能解决你的问题,请参考以下文章