web-dev-qa-db-ja.com

WITH句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

これらの3つのWITHASセクションをUNIONしようとすると助けが必要です。次のエラーが発生します。 Error Message when trying to UNION Multiple WITH AS

WITH ASが1つだけ使用されているクエリ

1
zac

2つの問題があります。まず、CTE間にコンマが必要です。次に、UNIONedステートメントのグループに対して1つのORDERBYしか持つことができません。最後に1つのORDERBYを使用するだけです。

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)



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)


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
3
Kenneth Fisher

ネストされたCTEについて一言で言えば、参照されるたびに評価されます。別の言い方をすれば、それらは一時テーブルのように動作せず、データは特別な方法でキャッシュされません。したがって、CTEが複数回参照されている場合(つまり、UNIONで1回、RunningTotalサブクエリで1回)、パフォーマンスが低下する可能性があります。これを示すために、クエリと数百行のみを使用して単純なリグを設定しました。最初の呼び出し(43,070回の読み取り)はクエリです。次の4回は、一時テーブルを使用して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

結果: enter image description here

この書き換えをデータで試して、読み取りを比較し、違いが見られた場合はお知らせください。

'In'についての別の言葉-それはあなたが思っているように振る舞わない。したがって、クエリ内のすべての「In」参照を「=」に変換しました。これがうまくいかない場合は、変数@ Projectlisting、@ ToPeriod、@ RecordTypesのサンプル値を投稿してください。それまでの間、このトピックに関するErlandSommarskogの優れた記事を確認することをお勧めします。

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

5
wBob