WITH 子句 UNION 问题

zac*_*zac 1 sql-server cte union

WITH [ProgressInvoicesPeriodCost] AS
(
    SELECT
        ProgressInvoices.ProjectId
        , ProgressInvoices.PeriodId
        , SUM(ProgressInvoiceDetails.TotalThisInvoice) AS TotalThisInvoice
    FROM
        CostManagement_ProgressInvoices AS ProgressInvoices
        LEFT JOIN CostManagement_ProgressInvoiceDetails AS ProgressInvoiceDetails
            ON  ProgressInvoices.Id = ProgressInvoiceDetails.ProgressInvoiceId
    WHERE
        ProgressInvoices.ProjectId IN (@Projectlisting)

    GROUP BY
        ProgressInvoices.ProjectId
        , ProgressInvoices.PeriodId
)

[CommitmentCOPeriodCost] AS
(
    SELECT
        CommitmentCOs.ProjectId
        , CommitmentCODetails.PeriodId
        , SUM(CommitmentCODetails.AmountApproved) AS AmountApproved
    FROM
        CostManagement_CommitmentCOs AS CommitmentCOs
        LEFT JOIN CostManagement_CommitmentCODetails AS CommitmentCODetails
            ON  CommitmentCOs.Id = CommitmentCODetails.CommitmentCOId
    WHERE
        CommitmentCOs.ProjectId IN (@Projectlisting) AND CommitmentCOs.PostAsId = 2

    GROUP BY
        CommitmentCOs.ProjectId
        , CommitmentCODetails.PeriodId
)

[CommitmentPeriodCost] AS
(
    SELECT
        Commitments.ProjectId
        , CommitmentDetails.PeriodId
        , SUM(CommitmentDetails.TotalCost) AS TotalCost

    FROM
        CostManagement_Commitments AS Commitments
        LEFT JOIN CostManagement_CommitmentDetails AS CommitmentDetails
            ON  Commitments.Id = CommitmentDetails.CommitmentId
    WHERE
        Commitments.ProjectId IN (@Projectlisting)

    GROUP BY
        Commitments.ProjectId
        , CommitmentDetails.PeriodId
)




SELECT
    ProjectId
    ,ProjectName
    ,'INV' as GroupRecordType
    ,'INV' as RecordType
    , PeriodId
    , Periods.Period
    , TotalThisInvoice AS TotalCost
    , (
            SELECT  SUM(TotalThisInvoice)
            FROM    ProgressInvoicesPeriodCost AS RunningCost
            WHERE   ProjectId = ProgressInvoicesPeriodCost.ProjectId
                    AND PeriodId <= ProgressInvoicesPeriodCost.PeriodId
    ) AS RunningTotal

FROM
    [ProgressInvoicesPeriodCost]
LEFT OUTER JOIN Periods
            ON  ProgressInvoicesPeriodCost.PeriodId = Periods.Id
LEFT OUTER JOIN Projects
            ON ProgressInvoicesPeriodCost.ProjectId = Projects.Id

Where (Period <= @ToPeriod) and ProgressInvoicesPeriodCost.ProjectId IN (@Projectlisting)AND 'INV' IN (@RecordTypes)


ORDER BY
    ProjectId
    , Period


UNION


SELECT
    ProjectId
    ,ProjectName
    ,'COM' as GroupRecordType
    ,'CO' as RecordType
    , PeriodId
    , Periods.Period
    , AmountApproved AS TotalCost
    , (
            SELECT  SUM(AmountApproved)
            FROM    CommitmentCOPeriodCost AS RunningCost
            WHERE   ProjectId = CommitmentCOPeriodCost.ProjectId
                    AND PeriodId <= CommitmentCOPeriodCost.PeriodId
    ) AS RunningTotal

FROM
    [CommitmentCOPeriodCost]
LEFT OUTER JOIN Periods
            ON  CommitmentCOPeriodCost.PeriodId = Periods.Id
LEFT OUTER JOIN Projects
            ON CommitmentCOPeriodCost.ProjectId = Projects.Id

Where (Period <= @ToPeriod) and CommitmentCOPeriodCost.ProjectId IN (@Projectlisting)AND 'CO' IN (@RecordTypes)


ORDER BY
    ProjectId
    , Period

UNION

SELECT
    ProjectId
    ,ProjectName
    ,'COM' as GroupRecordType
    ,'COM' as RecordType
    , PeriodId
    , Periods.Period
    , TotalCost
    , (
            SELECT  SUM(TotalCost)
            FROM    CommitmentPeriodCost AS RunningCost
            WHERE   ProjectId = CommitmentPeriodCost.ProjectId
                    AND PeriodId <= CommitmentPeriodCost.PeriodId
    ) AS RunningTotal

FROM
    [CommitmentPeriodCost]
LEFT OUTER JOIN Periods
            ON  CommitmentPeriodCost.PeriodId = Periods.Id
LEFT OUTER JOIN Projects
            ON CommitmentPeriodCost.ProjectId = Projects.Id

Where (Period <= @ToPeriod) and CommitmentPeriodCost.ProjectId IN (@Projectlisting)AND 'COM' IN (@RecordTypes)

ORDER BY
    ProjectId
    , Period
Run Code Online (Sandbox Code Playgroud)

我需要帮助尝试将这 3 个与 AS 部分联合。我收到以下错误: 尝试 UNION Multiple WITH AS 时的错误消息

仅使用 1 个 WITH AS 进行查询

wBo*_*Bob 5

简单说一下嵌套 CTE,每次引用它们时都会对其进行评估。换句话说,它们的行为不像临时表,数据没有以某种特殊方式缓存。因此,对于像您一样多次引用的 CTE(即一次在 UNION 中,一次在 RunningTotal 子查询中),可能会降低性能。我用您的查询设置了一个简单的装备,只有几百行来演示这一点。第一个调用(43,070 次读取)是您的查询,接下来的四个一起是我使用临时表来缓存 CTE 结果的重写,总共只注册了 702 次读取:

IF OBJECT_ID('tempdb..#ProgressInvoicesPeriodCost') IS NOT NULL DROP TABLE tempdb..#ProgressInvoicesPeriodCost
IF OBJECT_ID('tempdb..#CommitmentCOPeriodCost') IS NOT NULL DROP TABLE tempdb..#CommitmentCOPeriodCost
IF OBJECT_ID('tempdb..#CommitmentPeriodCost') IS NOT NULL DROP TABLE tempdb..#CommitmentPeriodCost

;WITH [ProgressInvoicesPeriodCost] AS
(
    SELECT
        ProgressInvoices.ProjectId
        , ProgressInvoices.PeriodId
        , SUM(ProgressInvoiceDetails.TotalThisInvoice) AS TotalThisInvoice
    FROM
        CostManagement_ProgressInvoices AS ProgressInvoices
        LEFT JOIN CostManagement_ProgressInvoiceDetails AS ProgressInvoiceDetails
            ON  ProgressInvoices.Id = ProgressInvoiceDetails.ProgressInvoiceId
    WHERE
        ProgressInvoices.ProjectId = @Projectlisting

    GROUP BY
        ProgressInvoices.ProjectId
        , ProgressInvoices.PeriodId
)
SELECT *
INTO #ProgressInvoicesPeriodCost
FROM [ProgressInvoicesPeriodCost]

;WITH [CommitmentCOPeriodCost] AS
(
    SELECT
        CommitmentCOs.ProjectId
        , CommitmentCODetails.PeriodId
        , SUM(CommitmentCODetails.AmountApproved) AS AmountApproved
    FROM
        CostManagement_CommitmentCOs AS CommitmentCOs
        LEFT JOIN CostManagement_CommitmentCODetails AS CommitmentCODetails
            ON  CommitmentCOs.Id = CommitmentCODetails.CommitmentCOId
    WHERE
        CommitmentCOs.ProjectId = @Projectlisting 
        AND CommitmentCOs.PostAsId = 2

    GROUP BY
        CommitmentCOs.ProjectId
        , CommitmentCODetails.PeriodId
)
SELECT *
INTO #CommitmentCOPeriodCost
FROM [CommitmentCOPeriodCost]

;WITH [CommitmentPeriodCost] AS
(
    SELECT
        Commitments.ProjectId
        , CommitmentDetails.PeriodId
        , SUM(CommitmentDetails.TotalCost) AS TotalCost

    FROM
        CostManagement_Commitments AS Commitments
        LEFT JOIN CostManagement_CommitmentDetails AS CommitmentDetails
            ON  Commitments.Id = CommitmentDetails.CommitmentId
    WHERE
        Commitments.ProjectId = @Projectlisting

    GROUP BY
        Commitments.ProjectId
        , CommitmentDetails.PeriodId
)
SELECT *
INTO #CommitmentPeriodCost
FROM [CommitmentPeriodCost]


SELECT

     ProjectId
    ,ProjectName
    ,'INV' as GroupRecordType
    ,'INV' as RecordType
    , PeriodId
    , Periods.Period
    , TotalThisInvoice AS TotalCost
    , (
            SELECT  SUM(TotalThisInvoice)
            FROM    #ProgressInvoicesPeriodCost AS RunningCost
            WHERE   ProjectId = ProgressInvoicesPeriodCost.ProjectId
                    AND PeriodId <= ProgressInvoicesPeriodCost.PeriodId
    ) AS RunningTotal

FROM
    #ProgressInvoicesPeriodCost ProgressInvoicesPeriodCost
LEFT OUTER JOIN Periods
            ON  ProgressInvoicesPeriodCost.PeriodId = Periods.Id
LEFT OUTER JOIN Projects
            ON ProgressInvoicesPeriodCost.ProjectId = Projects.Id

WHERE (Period <= @ToPeriod)
  AND ProgressInvoicesPeriodCost.ProjectId = @Projectlisting
  AND 'INV' = @RecordTypes

UNION ALL

SELECT
    ProjectId
    ,ProjectName
    ,'COM' as GroupRecordType
    ,'CO' as RecordType
    , PeriodId
    , Periods.Period
    , AmountApproved AS TotalCost
    , (
            SELECT  SUM(AmountApproved)
            FROM    #CommitmentCOPeriodCost AS RunningCost
            WHERE   ProjectId = CommitmentCOPeriodCost.ProjectId
                    AND PeriodId <= CommitmentCOPeriodCost.PeriodId
    ) AS RunningTotal

FROM
    #CommitmentCOPeriodCost CommitmentCOPeriodCost
LEFT OUTER JOIN Periods
            ON  CommitmentCOPeriodCost.PeriodId = Periods.Id
LEFT OUTER JOIN Projects
            ON CommitmentCOPeriodCost.ProjectId = Projects.Id

WHERE (Period <= @ToPeriod) and CommitmentCOPeriodCost.ProjectId = @Projectlisting
 AND 'CO' = @RecordTypes

UNION ALL

SELECT
    ProjectId
    ,ProjectName
    ,'COM' as GroupRecordType
    ,'COM' as RecordType
    , PeriodId
    , Periods.Period
    , TotalCost
    , (
            SELECT  SUM(TotalCost)
            FROM    #CommitmentPeriodCost AS RunningCost
            WHERE   ProjectId = CommitmentPeriodCost.ProjectId
                    AND PeriodId <= CommitmentPeriodCost.PeriodId
    ) AS RunningTotal

FROM
    #CommitmentPeriodCost CommitmentPeriodCost
LEFT OUTER JOIN Periods
            ON  CommitmentPeriodCost.PeriodId = Periods.Id
LEFT OUTER JOIN Projects
            ON CommitmentPeriodCost.ProjectId = Projects.Id

Where (Period <= @ToPeriod) and CommitmentPeriodCost.ProjectId = @Projectlisting
AND 'COM' = @RecordTypes

ORDER BY
    ProjectId
    , Period
Run Code Online (Sandbox Code Playgroud)

结果: 在此处输入图片说明

尝试用您的数据重写,比较读取,如果您发现差异,请告诉我们。

关于“In”的另一个词 - 它的行为方式与您认为的方式不同。因此,我已将查询中的所有“In”引用转换为“=”。如果这对您不起作用,请为您的变量@Projectlisting、@ToPeriod 和@RecordTypes 发布示例值。同时,您可能希望查看 Erland Sommarskog 关于此主题的出色文章

http://www.sommarskog.se/arrays-in-sql.html