组中的标量子查询是一种不好的做法吗?

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 JOINJOIN 比子查询性能更高。

有什么用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 发生在 聚合之前 并且有一个额外的聚合键。但是,我认为这对性能的影响非常小,因为它已经在进行聚合。

如果这是一个问题,您可以使用子查询来获得基本相同的执行计划。