-1

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

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;
4

3 回答 3

1

您在SELECT子句中使用了子查询,我发现它在这里非常合适。

该表BE_ENLEVEMENT在此处用作查找表,您可以在其中BE_Commercial查找每个 selected的表xIdBeBE_Commercial如果您改用 join ,我不会看到per只有一个xIdBe.

这意味着 select 子句中的子查询使查询更容易理解,这很好。可读性增强了可维护性。

于 2019-07-19T09:01:22.910 回答
1

如果插入大量数据,您当前的查询将产生糟糕的性能。

如果它插入几行,比如 10 行,那么你可以忽略它。

Scalar UDF应该避免在WHERE ,JOIN,GROUP BY.It 执行 Like RBAR。它将为每一行执行。

您可以Inline TVFInner 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

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

然后你可以一个一个地做改变。每一步都会有改进。

于 2019-07-19T11:35:07.763 回答
1

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

事实上,相关子查询可能非常有用,但逻辑​​通常是使用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发生聚合之前并且有一个额外的聚合键。但是,我认为这对性能的影响非常小,因为它已经在进行聚合。

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

于 2019-07-19T11:39:13.380 回答