查询嵌套查询结果中两列的位置

时间:2011-01-26 01:19:45

标签: sql sql-server tsql sql-server-2008 query-optimization

我正在编写这样的查询:

select * from myTable where X in (select X from Y) and XX in (select X from Y)

列X和XX的值必须位于同一查询的结果中:select X from Y

我认为这个查询被调用了两次所以它毫无意义。还有其他选择我可以更有效地编写此查询吗?也许临时表?

4 个答案:

答案 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,5x.x = 2x.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 更容易看到,在两种情况下都使用相同的东西。非常类似于将长函数分解为子例程

Docs on MSDN

答案 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子句并创建内存表。