我有一个复杂的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语句进行更改或重新构造查询。
答案 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开发人员非常强大的工具,特别是当用作递归查询时