组中的标量子查询是一种不好的做法吗?
Are scalar subqueries in a group by a bad practice?
我有这个问题。应该避免嵌套 select 吗?有没有更好的方法?
WITH cte(oi, oIdOf) AS (
SELECT ROW_NUMBER() OVER (ORDER BY resIdOf), resIdOf
FROM @res
WHERE resIdOf<>0
GROUP BY resIdOf
)
INSERT INTO @fop
SELECT x.xIdOf
,x.xIdBe
,x.xLgnBe
,(SELECT e.BE_Commercial FROM BE_ENLEVEMENT AS e WHERE e.BE_Numero_BE=x.xIdBe)
,SUM(x.xCoeff)
FROM cte AS o
CROSS APPLY dbo.ft_grapheOfOrigine(o.oIdOf) AS x
GROUP BY x.xIdOf,x.xIdBe,x.xLgnBe;
您在 SELECT
子句中使用了子查询,我发现它在这里非常合适。
table BE_ENLEVEMENT
在这里用作查找 table,在这里您可以为每个 selected xIdBe
查找 BE_Commercial
].如果您改用联接,我不会看到每个 xIdBe
.
只有一个 BE_Commercial
这意味着 select 子句中的子查询使查询更容易理解,这很好。可读性增强了可维护性。
如果插入大量数据,您当前的查询性能会很差。
如果插入的行很少,比如 10 行,那么您可以忽略它。
Scalar UDF
应避免出现在 WHERE ,JOIN,GROUP BY
中。它的执行方式类似于 RBAR
。它将针对每一行执行。
您可以使用 Inline TVF
并在 Inner join
条件下使用它而不是 CROSS APPLY
。
或者,如果您使用 CROSS APPLY
,则将 TVF logic
写入 CROSS APPLY
本身。
子查询错误。使用 TOP 1
是安全的
(SELECT TOP 1 e.BE_Commercial FROM BE_ENLEVEMENT AS e WHERE e.BE_Numero_BE=x.xIdBe)
你也应该避免 sub query
。请改用 LEFT JOIN
。
JOIN
比子查询性能更高。
有什么用ROW_NUMBER() OVER (ORDER BY resIdOf)
在你的query.I中没看到它在INSERT
中的用途。如果真的是这样那么你可以避免昂贵的WINDOW Function
。
您可以使用工具提示截取屏幕截图或保存现有查询的计划。
然后你就可以一点一点的改了,每一步都会有进步的。
我不喜欢带聚合的相关子查询。聚合条件可能很难正确设置,因为相关条件需要在聚合之后引用值。
事实上,相关子查询可能非常有用,但逻辑通常是使用 LEFT JOIN
实现的。
更重要的是,重写它们真的很简单。所以:
SELECT x.xIdOf, x.xIdBe, x.xLgnBe,
e.BE_Commercial,
SUM(x.xCoeff)
FROM cte o CROSS APPLY
dbo.ft_grapheOfOrigine(o.oIdOf) AS x LEFT JOIN
BE_ENLEVEMENT e
ON e.BE_Numero_BE = x.xIdBe
GROUP BY x.xIdOf, x.xIdBe, x.xLgnBe, e.BE_Commercial;
从性能的角度来看,这与您的查询不完全相同,因为 JOIN
发生在 聚合之前 并且有一个额外的聚合键。但是,我认为这对性能的影响非常小,因为它已经在进行聚合。
如果这是一个问题,您可以使用子查询来获得基本相同的执行计划。
我有这个问题。应该避免嵌套 select 吗?有没有更好的方法?
WITH cte(oi, oIdOf) AS (
SELECT ROW_NUMBER() OVER (ORDER BY resIdOf), resIdOf
FROM @res
WHERE resIdOf<>0
GROUP BY resIdOf
)
INSERT INTO @fop
SELECT x.xIdOf
,x.xIdBe
,x.xLgnBe
,(SELECT e.BE_Commercial FROM BE_ENLEVEMENT AS e WHERE e.BE_Numero_BE=x.xIdBe)
,SUM(x.xCoeff)
FROM cte AS o
CROSS APPLY dbo.ft_grapheOfOrigine(o.oIdOf) AS x
GROUP BY x.xIdOf,x.xIdBe,x.xLgnBe;
您在 SELECT
子句中使用了子查询,我发现它在这里非常合适。
table BE_ENLEVEMENT
在这里用作查找 table,在这里您可以为每个 selected xIdBe
查找 BE_Commercial
].如果您改用联接,我不会看到每个 xIdBe
.
BE_Commercial
这意味着 select 子句中的子查询使查询更容易理解,这很好。可读性增强了可维护性。
如果插入大量数据,您当前的查询性能会很差。
如果插入的行很少,比如 10 行,那么您可以忽略它。
Scalar UDF
应避免出现在 WHERE ,JOIN,GROUP BY
中。它的执行方式类似于 RBAR
。它将针对每一行执行。
您可以使用 Inline TVF
并在 Inner join
条件下使用它而不是 CROSS APPLY
。
或者,如果您使用 CROSS APPLY
,则将 TVF logic
写入 CROSS APPLY
本身。
子查询错误。使用 TOP 1
(SELECT TOP 1 e.BE_Commercial FROM BE_ENLEVEMENT AS e WHERE e.BE_Numero_BE=x.xIdBe)
你也应该避免 sub query
。请改用 LEFT JOIN
。
JOIN
比子查询性能更高。
有什么用ROW_NUMBER() OVER (ORDER BY resIdOf)
在你的query.I中没看到它在INSERT
中的用途。如果真的是这样那么你可以避免昂贵的WINDOW Function
。
您可以使用工具提示截取屏幕截图或保存现有查询的计划。
然后你就可以一点一点的改了,每一步都会有进步的。
我不喜欢带聚合的相关子查询。聚合条件可能很难正确设置,因为相关条件需要在聚合之后引用值。
事实上,相关子查询可能非常有用,但逻辑通常是使用 LEFT JOIN
实现的。
更重要的是,重写它们真的很简单。所以:
SELECT x.xIdOf, x.xIdBe, x.xLgnBe,
e.BE_Commercial,
SUM(x.xCoeff)
FROM cte o CROSS APPLY
dbo.ft_grapheOfOrigine(o.oIdOf) AS x LEFT JOIN
BE_ENLEVEMENT e
ON e.BE_Numero_BE = x.xIdBe
GROUP BY x.xIdOf, x.xIdBe, x.xLgnBe, e.BE_Commercial;
从性能的角度来看,这与您的查询不完全相同,因为 JOIN
发生在 聚合之前 并且有一个额外的聚合键。但是,我认为这对性能的影响非常小,因为它已经在进行聚合。
如果这是一个问题,您可以使用子查询来获得基本相同的执行计划。