ala*_*ala 161 sql-server
我需要在SQL Server中实现以下查询:
select *
from table1
WHERE (CM_PLAN_ID,Individual_ID)
IN
(
Select CM_PLAN_ID, Individual_ID
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
)
Run Code Online (Sandbox Code Playgroud)
但WHERE..IN子句只允许1列.如何将2个或更多列与另一个内部SELECT进行比较?
mrd*_*nny 118
您将要使用WHERE EXISTS语法.
SELECT *
FROM table1
WHERE EXISTS (SELECT *
FROM table2
WHERE Lead_Key = @Lead_Key
AND table1.CM_PLAN_ID = table2.CM_PLAN_ID
AND table1.Individual_ID = table2.Individual_ID)
Run Code Online (Sandbox Code Playgroud)
sle*_*ske 102
您可以从子查询中创建派生表,并将table1连接到此派生表:
select * from table1 LEFT JOIN
(
Select CM_PLAN_ID, Individual_ID
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
) table2
ON
table1.CM_PLAN_ID=table2.CM_PLAN_ID
AND table1.Individual=table2.Individual
WHERE table2.CM_PLAN_ID IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
gbn*_*gbn 12
一个简单的EXISTS子句是最干净的
select *
from table1 t1
WHERE
EXISTS
(
Select * --or 1. No difference.
From CRM_VCM_CURRENT_LEAD_STATUS Ex
Where Lead_Key = :_Lead_Key
-- correlation here
AND
t1.CM_PLAN_ID = Ex.CM_PLAN_ID AND t1.CM_PLAN_ID = Ex.Individual_ID
)
Run Code Online (Sandbox Code Playgroud)
如果在关联中有多行,则JOIN会在输出中提供多行,因此您需要使用不同的行.这通常使EXISTS更有效率.
注意带有JOIN的"SELECT"*也包括行限制表中的列
小智 12
select * from tab1 where (col1,col2) in (select col1,col2 from tab2)
Run Code Online (Sandbox Code Playgroud)
注意:
Oracle会忽略一个或多个所选列为NULL的行.在这些情况下,您可能希望使用NVL -Funktion将NULL映射到特殊值(不应该在值中);
select * from tab1
where (col1, NVL(col2, '---') in (select col1, NVL(col2, '---') from tab2)
Run Code Online (Sandbox Code Playgroud)
Den*_*din 11
如果您是唯一创建表的人,那么这可能并不重要,但是当其中一个表可能不包含唯一行时,几种解决方案将提供与所讨论代码不同数量的输出行。
当我看到包含两列的输入时,我可以想象它意味着两件事:
方案1相当简单,只需使用两个IN语句即可。
与大多数现有答案相一致,我在此概述方案2(以及简要判断)中提到的方法和其他方法:
正如@mrdenny提供的那样,EXISTS听起来完全符合您的要求,这是他的示例:
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
Run Code Online (Sandbox Code Playgroud)
这是一种非常简洁的连接方式,但是不幸的是,大多数SQL方言,包括SQL Server,目前都不支持它。
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
Run Code Online (Sandbox Code Playgroud)
正如@cataclysm所提到的,使用两个IN语句也可以解决问题,也许它甚至会胜过其他解决方案。但是,您应该非常小心的是代码重复。如果您要从其他表中进行选择,或者更改where语句,则可能会增加逻辑不一致的风险。
基本解决方案
SELECT * from T1
WHERE a IN (SELECT a FROM T2 WHERE something)
AND b IN (SELECT b FROM T2 WHERE something)
Run Code Online (Sandbox Code Playgroud)
没有代码重复的解决方案(我相信这在常规SQL Server查询中不起作用)
WITH mytmp AS (SELECT a, b FROM T2 WHERE something);
SELECT * from T1
WHERE a IN (SELECT a FROM mytmp)
AND b IN (SELECT b FROM mytmp)
Run Code Online (Sandbox Code Playgroud)
我不建议使用内部联接作为过滤器的原因是,在实践中,人们经常让右表中的重复项导致左表中的重复项。然后使情况更糟的是,它们有时使最终结果变得与众不同,而左表实际上可能不需要唯一(或者在您选择的列中不是唯一的)。此外,它还使您有机会实际选择左表中不存在的列。
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
Run Code Online (Sandbox Code Playgroud)
最常见的错误:
功能上的问题是,如果使用可能在列中出现的分隔符,则很难确保结果是100%准确的。技术上的问题是此方法通常会导致类型转换,并且会完全忽略索引,从而可能导致可怕的性能。尽管存在这些问题,但我不得不承认,有时我仍将其用于小型数据集的临时查询。
SELECT * FROM T1
WHERE CONCAT(a,"_",b) IN
(SELECT CONCAT(a,"_",b) FROM T2)
Run Code Online (Sandbox Code Playgroud)
请注意,如果您的列是数字列,则某些SQL方言将要求您首先将它们转换为字符串。我相信SQL Server会自动执行此操作。
总结:像往常一样,在SQL中有很多方法可以做到这一点,使用安全的选择可以避免意外情况,从长远来看可以节省时间和精力。