Answers:
您可以从子查询中创建一个派生表,并将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
您将改为使用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)
如果您是唯一创建表的人,那么这可能无关紧要,但是当其中一个表可能不包含唯一行时,几种解决方案将提供与所讨论代码不同数量的输出行。
当我看到包含两列的输入时,我可以想象它意味着两件事:
方案1相当简单,只需使用两个IN语句即可。
与大多数现有答案相一致,我在此概述方案2(以及简要判断)中提到的方法和其他方法:
正如@mrdenny提供的那样,EXISTS听起来完全符合您的要求,这是他的示例:
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
这是一种非常简洁的连接方式,但是不幸的是,大多数SQL方言,包括SQL Server,目前都不支持它。
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
正如@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)
我不建议使用内部联接作为过滤器的原因是,在实践中,人们经常让右表中的重复项导致左表中的重复项。然后使情况更糟的是,它们有时使最终结果与众不同,而实际上左表可能不需要唯一(或在您选择的列中不是唯一的)。此外,它还使您有机会实际选择左表中不存在的列。
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
最常见的错误:
功能上的问题是,如果使用可能在列中出现的分隔符,则很难确保结果是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)
where (colA,colB) in (... some list of tuples...)
但我不确定其他数据库也可以这样做。我很想知道。
一个简单的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
)
如果关联中有多行,则JOIN在输出中给出多行,因此您需要与众不同。这通常会使EXISTS更加有效。
注意SELECT *
,使用JOIN还将包括行限制表中的列
当您可以执行普通的内部联接时,为什么要使用WHERE EXISTS或DERIVED TABLE:
SELECT t.*
FROM table1 t
INNER JOIN CRM_VCM_CURRENT_LEAD_STATUS s
ON t.CM_PLAN_ID = s.CM_PLAN_ID
AND t.Individual_ID = s.Individual_ID
WHERE s.Lead_Key = :_Lead_Key
如果状态表中的(CM_PLAN_ID,Individual_ID)对不是唯一的,则可能需要SELECT DISTINCT t。*。
Postgres SQL : version 9.6
Total records on tables : mjr_agent = 145, mjr_transaction_item = 91800
1.使用EXISTS
[平均查询时间:1.42s]
SELECT count(txi.id)
FROM
mjr_transaction_item txi
WHERE
EXISTS ( SELECT 1 FROM mjr_agent agnt WHERE agnt.agent_group = 0 AND (txi.src_id = agnt.code OR txi.dest_id = agnt.code) )
2.使用两行IN
子句[平均查询时间:0.37s]
SELECT count(txi.id) FROM mjr_transaction_item txi
WHERE
txi.src_id IN ( SELECT agnt.code FROM mjr_agent agnt WHERE agnt.agent_group = 0 )
OR txi.dest_id IN ( SELECT agnt.code FROM mjr_agent agnt WHERE agnt.agent_group = 0 )
3.与INNNER JOIN
模式一起使用[平均查询时间:2.9s]
SELECT count(DISTINCT(txi.id)) FROM mjr_transaction_item txi
INNER JOIN mjr_agent agnt ON agnt.code = txi.src_id OR agnt.code = txi.dest_id
WHERE
agnt.agent_group = 0
因此,我选择了第二个选项。
AND
语句而不是OR
语句。
OR
声明可能会引起重复。在我的情况下,还没有包含任何相同的行src_id
和dest_id
在单行。因此,在我的情况下不会发生重复。
查询:
select ord_num, agent_code, ord_date, ord_amount
from orders
where (agent_code, ord_amount) IN
(SELECT agent_code, MIN(ord_amount)
FROM orders
GROUP BY agent_code);
上面的查询在mysql中为我工作。参考以下链接->
https://www.w3resource.com/sql/subqueries/multiplee-row-column-subqueries.php
如果要一张表,请使用以下查询
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
id in (1,2) and studentName in ('a','b')
与完全不同(id, studentName) in ((1,'a'),(2,'b'))
。试想一下一条id = 2和name ='a'的记录。当然,如果ID是唯一的,那么效果会减弱,但是,如果ID是唯一的,我们根本不需要过滤名称。
以某种形式将列连接在一起是“黑客”,但是当产品不支持一个以上列的半联接时,有时您别无选择。
内部/外部连接解决方案不起作用的示例:
select * from T1
where <boolean expression>
and (<boolean expression> OR (ColA, ColB) in (select A, B ...))
and <boolean expression>
...
当查询本质上并不简单时,有时您无权访问基本表集以执行常规的内部/外部联接。
如果您确实使用此“ hack”,则在合并字段时,请务必在它们之间添加足够的定界符,以避免产生误解,例如 ColA + ":-:" + ColB
我这样更容易地建立
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
)
希望这个帮助:)
CM_PLAN_ID = 45
和Individual_ID = 3
再拼接的结果453
-这是从那里的情况下难以区分CM_PLAN_ID = 4
和Individual_ID = 53
...找麻烦我还以为
45_3
或,45:3
但是它仍然不是一个很好的解决方案,因为@mrdenny说,由于对列进行了转换,因此索引将不再被利用。