我需要在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
)
但是WHERE..IN子句只允许1列。我如何比较2个或更多的列与另一个内部选择?
我需要在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
)
但是WHERE..IN子句只允许1列。我如何比较2个或更多的列与另一个内部选择?
当前回答
关于解决方案的警告:
如果行不是唯一的,许多现有的解决方案将给出错误的输出
如果您是唯一创建表的人,这可能无关紧要,但是当其中一个表可能不包含唯一行的时候,一些解决方案将从相关代码中给出不同数量的输出行。
关于问题语句的警告:
在与多列不存在的情况下,仔细想想你想要什么
当我看到一个in有两列时,我可以想象它意味着两件事:
列a和列b的值分别出现在另一个表中 列a和列b的值一起出现在另一个表的同一行中
场景1相当简单,只需使用两个IN语句。
根据大多数现有的答案,我在此提供了关于场景2的上述和其他方法的概述(以及简短的判断):
EXISTS(安全,推荐用于SQL Server)
正如@mrdenny提供的,EXISTS听起来和你想要的完全一样,下面是他的例子:
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
LEFT SEMI JOIN(安全,推荐用于支持它的方言)
这是一种非常简洁的连接方式,但不幸的是,包括SQL server在内的大多数SQL方言目前都不支持它。
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
多个IN语句(安全,但要注意代码重复)
正如@cataclysm所提到的,使用两个IN语句也可以做到这一点,也许它甚至会优于其他解决方案。但是,您应该非常小心的是代码复制。如果您希望从不同的表中进行选择,或者更改where语句,则会增加在逻辑中产生不一致的风险。
基本的解决方案
SELECT * from T1
WHERE a IN (SELECT a FROM T2 WHERE something)
AND b IN (SELECT b FROM T2 WHERE something)
没有代码复制的解决方案(我相信这在常规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)
INNER JOIN(技术上可以使其安全,但通常不这样做)
我不建议使用内部连接作为过滤器的原因是,在实践中,人们经常让右表中的重复数据导致左表中的重复数据。然后更糟糕的是,它们有时会使最终结果不同,而左边的表实际上可能不需要是唯一的(或者在您选择的列中不是唯一的)。此外,它让您有机会实际选择左表中不存在的列。
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
最常见的错误:
直接在T2上连接,没有安全的子查询。导致重复的风险) SELECT *(保证从T2中获取列) SELECT c(不保证你的列总是来自T1) 在错误的地方没有DISTINCT或DISTINCT
列与分隔符的连接(不是很安全,性能很糟糕)
功能问题是,如果您使用分隔符可能出现在列中,则很难确保结果是100%准确的。技术上的问题是,这种方法经常会导致类型转换,并且完全忽略索引,从而可能导致糟糕的性能。 尽管存在这些问题,但我不得不承认,我有时仍然使用它对小型数据集进行特别查询。
SELECT * FROM T1
WHERE CONCAT(a,"_",b) IN
(SELECT CONCAT(a,"_",b) FROM T2)
请注意,如果您的列是数字的,一些SQL方言将要求您首先将它们转换为字符串。我相信SQL server会自动做到这一点。
总结一下:通常在SQL中有很多方法可以做到这一点,使用安全的选择将避免意外,并为您节省时间和长远的发展。
其他回答
select * from tab1 where (col1,col2) in (select col1,col2 from tab2)
注意: Oracle忽略一个或多个所选列为NULL的行。在这些情况下,你可能想要使用NVL-Funktion将NULL映射到一个特殊的值(不应该在值中);
select * from tab1
where (col1, NVL(col2, '---') in (select col1, NVL(col2, '---') from tab2)
你可以从子查询中创建一个派生表,并将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
我觉得这样更容易
Select *
from table1
WHERE (convert(VARCHAR,CM_PLAN_ID) + convert(VARCHAR,Individual_ID))
IN
(
Select convert(VARCHAR,CM_PLAN_ID) + convert(VARCHAR,Individual_ID)
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
)
希望这对你有所帮助:)
如果你想要一个表,然后使用以下查询
SELECT S.*
FROM Student_info S
INNER JOIN Student_info UT
ON S.id = UT.id
AND S.studentName = UT.studentName
where S.id in (1,2) and S.studentName in ('a','b')
并表中数据如下
id|name|adde|city
1 a ad ca
2 b bd bd
3 a ad ad
4 b bd bd
5 c cd cd
然后输出如下
id|name|adde|city
1 a ad ca
2 b bd bd
简单而错误的方法是使用+或连接两列并生成一列。
Select *
from XX
where col1+col2 in (Select col1+col2 from YY)
这会偏离轨道,很慢。不能在编程中使用,但如果你只是查询验证一些东西可能会被使用。