删除重复的子查询

时间:2016-02-29 08:46:33

标签: sql sql-server tsql common-table-expression dynamic-sql

我有一个复杂的SQL查询,可以简化为以下内容:

Select ColA,ColB,ColC,ColD
From MyTable
Where (ColA In (Select ItemID From Items Where ItemName like '%xxx%') 
    or ColB In (Select ItemID From Items Where ItemName like '%xxx%'))

如您所见,子查询出现两次。编译器是否足够智能来检测它并仅获取子查询的结果一次?或者子查询是否运行两次?

仅供参考,表项目大约有20,000行,MyTable有大约200,000行。

是否有另一种方法可以重写此SQL语句,以便子查询只出现/运行一次?

更新:主查询中的Where子句是动态的,仅在需要时添加(即仅在用户搜索&x; xxx'时)。因此,无法对主select语句进行更改或重新构造查询。

4 个答案:

答案 0 :(得分:17)

更新您的请求不要更改查询,只需WHERE

您可以将CTE直接打包到它被调用的地方(未经测试):

Select ColA,ColB,ColC,ColD
From MyTable
Where EXISTS (SELECT 1 FROM (Select i.ItemID 
                             From Items AS i 
                             Where iItemName like '%xxx%') AS itm 
              WHERE itm.ItemID=MyTable.ColA OR itm.ItemID=MyTable.ColB) 

我认为这应该是一样的......

WITH MyCTE AS
(
    Select ItemID From Items Where ItemName like '%xxx%'
)
Select ColA,ColB,ColC,ColD
From MyTable
Where EXISTS (SELECT 1 FROM MyCTE WHERE ItemID=ColA OR ItemID=ColB) 

子串LIKE搜索 - 肯定 - 不具备性能。

如果你可以减少你的"物品"使用LIKE过滤器只需几行,您必须测试哪一行最快。

答案 1 :(得分:2)

您也可以像这样编写查询:

SELECT ColA, ColB, ColC, ColD
FROM MyTable
WHERE EXISTS(
  (SELECT ItemID FROM Items WHERE ItemName LIKE '%xxx%') 
  INTERSECT
  SELECT t.v FROM (VALUES (ColA), (ColB)) AS t(v) )

答案 2 :(得分:1)

无法保证它会遵循实际的执行顺序。这取决于您如何编写查询。相同的子查询通常只执行一次。 标准SQL中有一个WITH子句。

WITH mySubQuery AS
(
  [the subquery code]
)

SELECT * FROM
    mySubQuery AS sq
WHERE xyz IN (mySubQuery)

答案 3 :(得分:1)

SQL程序员可以在这种情况下使用CTE(公用表表达式)

您可以使用子查询定义一次CTE,并通过多次引用在SQL语句中使用它。

有关样本,请参阅SQL CTE Common Table Expression tutorial CTE是SQL开发人员非常强大的工具,特别是当用作递归查询时

相关问题