【问题标题】:SQL Server Iterate through CTESQL Server 迭代 CTE
【发布时间】:2017-10-16 14:20:13
【问题描述】:

存储过程 #1:@Country 参数返回 1+ 行 OrganizationIDMeasurableID

存储过程 #2:@OrganizationID@MeasurableID 参数,创建一个 CTE(它使用 ROW_NUMBER() OVER (PARTITION BY Entities.ID ORDER BY Contracts.UTCmatched desc) 为每个 Entity 返回一个单独的行)

我试图将这些组合成一个存储过程,其中@Country 参数通过 SP1 代码返回(比如 5)行;然后通过 SP2 代码迭代每一行以返回一个表(如果有 20 个实体,则为 100 行)。

我尝试了嵌套和递归 CTE 均无济于事。我正在考虑将循环/光标和/或将最终结果填充到临时表中,但坦率地说,我有点迷失(并且超出了我的经验水平),所以希望主要是关于采取的方法的建议。

提前致谢。

SP1

        SELECT
            dbo.Measurables.OrganizationID,
            dbo.Measurables.ID AS MeasurableID

            FROM dbo.Measurables INNER JOIN dbo.Organizations ON dbo.Organizations.ID = dbo.Measurables.OrganizationID

            WHERE   dbo.Measurables.EndUTC > SYSUTCDATETIME ( )  
                AND dbo.Measurables.OrganizationID IN
                                        (
                                                SELECT
                                                    dbo.Countries2Organizations.OrganizationID
                                                FROM
                                                    dbo.Countries2Organizations
                                                WHERE
                                                    dbo.Countries2Organizations.Sport IN 
                                                        (
                                                            SELECT
                                                                dbo.Countries2Sports.SportName
                                                            FROM
                                                                dbo.Countries2Sports
                                                            WHERE
                                                                dbo.Countries2Sports.CountryCode = @CountryCode
                                                        )
                                                AND (   dbo.Countries2Organizations.CountryCode = @CountryCode  OR dbo.Countries2Organizations.CountryCode = '')

                                        )

--Result:     OrganizationID     MeasurableID
                    --1                 2017
                    --1                 2018
                    --2                 2021
                    --3                 2023

SP2

;WITH 
        LastScore as ( SELECT Entities.ID, Results.Score,
                                 Results.UTC,   
                                row_number() over (partition by Entities.ID ORDER BY Results.UTC desc) row1
                            FROM dbo.Entities 
                                INNER JOIN dbo.Results ON dbo.Results.EntityID = dbo.Entities.ID
                            WHERE dbo.Results.MeasurableID = @MeasurableID),


        PreviousScore as ( SELECT Entities.ID,  Results.Score,
                                 Results.UTC,   
                                row_number() over (partition by Entities.ID ORDER BY Results.UTC desc) row2
                            FROM dbo.Entities 
                                INNER JOIN dbo.Results ON dbo.Results.EntityID = dbo.Entities.ID
                            WHERE dbo.Results.MeasurableID = @MeasurableID )



    SELECT @OrganizationID AS OrganizationID, @MeasurableID AS MeasurableID, Entities.ID AS EntityID,    
              LastScore.Score AS LastScore, 
                    LastScore.Score - PreviousScore.Score AS Change,    LastScore.UTC 

    FROM Entities 
            LEFT JOIN LastScore on LastScore.ID = Entities.ID AND row1=1
            LEFT JOIN PreviousScore on PreviousScore.ID = Entities.ID AND row2=2

    WHERE dbo.Entities.OrganizationID = @OrganizationID 



--Result:
 --OrganizationID   MeasurableID   EntityID   LastScore   Change   UTC   
      --1              2017           1          15          2    4/6/17
      --1              2017           1          18         -3    4/8/17

【问题讨论】:

  • 能否请您粘贴您目前的工作情况
  • 为什么是 SP,而不是函数?
  • 是的,带有虚拟数据和所需输出的样本将帮助我们和您更好地理解问题
  • 看看这篇文章,它展示了如何提供一个可重新运行的示例数据集供我们使用:stackoverflow.com/a/43998463/57475
  • @Tanner Functions 更容易返回表数据(不允许嵌套insert..exec,临时表也不好)

标签: sql-server loops cursor common-table-expression temp-tables


【解决方案1】:

我推荐使用函数,而不是存储过程 它工作得更快:

1) 没有循环,数据将在一个查询中检索

2) 带有内联函数的查询优化器可以优化整个查询

以下是如何使用函数执行此操作的示例:

CREATE FUNCTION dbo.Func1 (
    @Country    INT
)
RETURNS TABLE
RETURN
    SELECT
        dbo.Measurables.OrganizationID,
        dbo.Measurables.ID AS MeasurableID
    FROM dbo.Measurables
...

CREATE FUNCTION dbo.Func2 (
    @OrganizationID  INT,
    @MeasurableID    INT
)
RETURNS TABLE
RETURN
    WITH 
        LastScore as ( SELECT Entities.ID, Results.Score,
                             Results.UTC,   
...


SELECT *
FROM dbo.Func1(@Country)                    F1
CROSS APPLY dbo.Func2(F1.OrganizationID, F1.MeasurableID) F2

【讨论】:

  • 太棒了!功能和 CROSS APPLY 就像一个魅力!再次感谢。
  • 在这个问题之后,Cross Apply 运行了 15-18 秒(对于仍然是开发/小型 Azure 托管数据库)。因此,我将第一个函数的结果移到了 UserDefinedType: Table 中,并且能够(包括减小某些表的大小)将结果缩短到 2 秒。但是,下一个要求是只能从货币列表中指定结果。我为货币创建了一个 UDT:表,并且可以将它传递给函数,但是对于四 (4) 个 MeasurableID 和四 (4) 个货币,最多可以返回 18 秒。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 2017-01-17
  • 2012-04-23
  • 2019-08-28
相关资源
最近更新 更多