さまざまなテーブルの行データを列として表示するレポートとして機能するビューを作成しています。場合によっては、連結が含まれます。一時テーブルを使用するとクエリはうまく機能しますが、ビューである必要があり、一時テーブルのアプローチをサブクエリに変換することに取り組んでいます。
この質問をできるだけ単純化するために、いくつかのサンプルテーブルとデータを作成しました。スキーマは次のとおりです。
CREATE TABLE [Car] (
[CarId] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Car] PRIMARY KEY CLUSTERED ([CarId] ASC))
INSERT INTO [Car] VALUES
(1, 'Honda')
CREATE TABLE [Part] (
[PartId] [int] IDENTITY(1,1) NOT NULL,
[CarId] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
[PercentComplete] [decimal](3, 2) NOT NULL,
CONSTRAINT [PK_Part] PRIMARY KEY CLUSTERED ([PartId] ASC))
INSERT INTO [Part] VALUES
(1, 'Engine', 0.5)
,(1, 'Transmission', 0.75)
,(1, 'Suspension', 0.3)
最初のステップは次のとおりです。
SELECT
c.CarId
,c.Name AS [CarName]
,p.Name AS [PartName]
,p.PercentComplete AS [PartPercentComplete]
INTO #Temp
FROM Car c
JOIN Part p
ON p.CarId = c.CarId
これが、レポートビューに変換するグループ化された選択です。
SELECT
MAX(CarName) AS [Car Name]
,STUFF((
SELECT ', ' + [PartName]
FROM #Temp
WHERE (CarId = t1.CarId)
FOR XML PATH (''))
,1,2,'') AS [Parts]
,MAX(CASE [PartCompleteAvg] WHEN 1.00 THEN 'Complete' ELSE 'Incomplete' END) AS [Part Status]
,MAX(CASE [PartId] WHEN [LatestPartId] THEN [PartName] ELSE NULL END) AS [Latest Part]
FROM (
SELECT
CarId
,AVG(PartPercentComplete) AS [PartCompleteAvg]
,MAX(PartId) AS [LatestPartId]
FROM #Temp
GROUP BY CarId
) t1
LEFT JOIN #Temp t2
ON t2.CarId = t1.CarId
GROUP BY t1.CarId
AVG(PartPercentComplete)
中間の集計関数ととの連結トリックのためにビューに変換するのに問題があることを除いて、それは素晴らしい働きをしSTUFF
ます。私のレポートには、これらのそれぞれのいくつかが必要です。
私はそれが与えるように私がAVG()
中に巣を作ることができないことを知っていますMAX()
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
(参考までに、私は知っていますが、複数の列PIVOT
にまたがる必要がありますが、それも可能であると認識していますが、簡単に思え、より速く言われます。)CASE
私の完全に間違った貧弱な試み:
SELECT
MAX(CarName) AS [Car Name]
,STUFF((
SELECT ', ' + [PartName]
FROM #Temp
WHERE (CarId = t1.CarId)
FOR XML PATH (''))
,1,2,'') AS [Parts]
,MAX(CASE [PartCompleteAvg] WHEN 1.00 THEN 'Complete' ELSE 'Incomplete' END) AS [Part Status]
FROM (
SELECT
CarId
,AVG(PartPercentComplete) AS [PartCompleteAvg]
FROM (
SELECT
c.CarId
,c.Name AS [CarName]
,p.Name AS [PartName]
,p.PercentComplete AS [PartPercentComplete]
FROM Car c
JOIN Part p
ON p.CarId = c.CarId
) t1
GROUP BY CarId
) t1
LEFT JOIN #Temp t2
ON t2.CarId = t1.CarId
GROUP BY t1.CarId
明らか#Temp
に、両方の場所で無効です。私はSQLの専門家ではないので、これを行うためのクリーンで比較的簡単な方法があり、自己参加を回避できることを望んでいます。
編集
追加しました
MAX(PartId) AS [LatestPartId]
と
MAX(CASE [PartId] WHEN [LatestPartId] THEN [PartName] ELSE NULL END) AS [Latest Part]
それは私が中間体を必要とする理由のより良い例だからですGROUP BY
。