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



我有这个查询。是否应该避免嵌套选择?有没有更好的方法?

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;

我不喜欢将子查询与聚合相关联。 聚合条件可能很难正确,因为相关条件需要引用聚合的值。

事实上,相关的子查询可能非常有用,但无论如何,逻辑通常都使用 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子句中使用了子查询,我觉得它在这里非常合适。

该表BE_ENLEVEMENT在此处用作查找表,您可以在其中查找每个选定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)有什么用。我没有看到它在INSERT中使用.如果真的是这样,那么您可以避免昂贵的WINDOW Function

您可以使用工具提示截取屏幕截图或保存现有查询的计划。

然后你可以 一一做 更改 .每一步都会有改进。

相关内容

  • 没有找到相关文章

最新更新