我正在编写这样的查询:
select * from myTable where X in (select X from Y) and XX in (select X from Y)
列X和XX的值必须位于同一查询的结果中:select X from Y
。
我认为这个查询被调用了两次所以它毫无意义。还有其他选择我可以更有效地编写此查询吗?也许临时表?
答案 0 :(得分:4)
实际上没有,没有更聪明的方法来写这个(没有访问Y两次),因为myTable.X和myTable.YY匹配的X可能不是来自同一行。
作为替代方案,查询的EXISTS形式是
select *
from myTable A
where exists (select * from Y where A.X = Y.X)
and exists (select * from Y where A.XX = Y.X)
如果Y包含1,2,3,4,5
,x.x = 2
和x.xx = 4
的X值,则它们都存在(在Y中的不同记录中),myTable中的记录应显示在输出中。< / p>
编辑:之前的回答声明You could rewrite this using _EXISTS_ clauses which will work faster than _IN_
。正如Martin指出的那样,这不是真的(当然不适用于SQL Server 2005及更高版本)。见链接
答案 1 :(得分:1)
尝试通过仅引用Y
一次来编写此查询可能不是特别有效。但是,鉴于您使用的是SQL Server 2008,可以使用以下变体:
Select ...
From MyTable As T
Where Exists (
Select 1
From Y
Where Y.X = T.X
Intersect
Select 1
From Y
Where Y.X = T.XX
)
<强>加成强>
实际上,我可以想到一种方法,你可以在不使用Y
多次的情况下做到这一点(没有人说过多次使用MyTable
)。然而,这更多是出于学术原因,因为我认为使用我的第一个解决方案可能会表现得更好:
Select ...
From MyTable As T
Where Exists (
Select 1
From Y
Where Exists(
Select 1
From MyTable1 As T1
Where T1.X = Y.X
Intersect
Select 1
From MyTable1 As T2
Where T2.XX = Y.X
)
And Y.X In(T.X, T.XX)
)
答案 2 :(得分:0)
WITH
w_tmp AS(
SELECT x
FROM y
)
SELECT *
FROM myTable
WHERE x IN (SELECT x FROM w_tmp)
AND xx IN (SELECT x FROM w_tmp)
(我在Oracle文档中已经阅读过这篇文章,但我认为MS也能够做到这一优化) 这样,优化器肯定知道你正在进行相同的查询,并且可以创建临时表到现金结果(但是仍然需要优化器来决定它是否值得。对于微小的查询,创建临时表的开销可能太高)。
另外(实际上这对我来说更重要),当子查询为50行时, human 更容易看到,在两种情况下都使用相同的东西。非常类似于将长函数分解为子例程
答案 3 :(得分:0)
不确定问题是什么但不简单加入答案?
SELECT t.*
FROM myTable
JOIN Y y1 ON y1.X = myTable.X
JOIN Y y2 ON y2.X = myTable.XX
或
SELECT t.*
FROM myTable, Y y1, Y y2
WHERE y1.X = myTable.X AND y2.X = myTable.XX
ADDED:如果强烈需要消除Y的第二个查询,让我们颠倒逻辑:
;WITH A(X)
AS (
-- this will select all values that can be found in Y and myTable X and XX fields.
SELECT Y.X -- if there are a lot of dups, add DISTINCT
FROM Y, myTable
WHERE Y.X IN (myTable.X, myTableXX)
)
-- now join back to the orignal table and filter.
SELECT t.*
FROM myTable
-- similar to what has been mentioned before
WHERE EXISTS(SELECT TOP 1 * from A where A.X = myTable.X)
AND EXISTS(SELECT TOP 1 * from A where A.X = myTable.XX)
如果您不喜欢WITH,可以使用SELECT INTO子句并创建内存表。