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しようとすると助けが必要です。次のエラーが発生します。 !
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
ネストされた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
結果:
この書き換えをデータで試して、読み取りを比較し、違いが見られた場合はお知らせください。
'In'についての別の言葉-それはあなたが思っているように振る舞わない。したがって、クエリ内のすべての「In」参照を「=」に変換しました。これがうまくいかない場合は、変数@ Projectlisting、@ ToPeriod、@ RecordTypesのサンプル値を投稿してください。それまでの間、このトピックに関するErlandSommarskogの優れた記事を確認することをお勧めします。