我有以下表格
BatchID Name CustomerID DateCreated Status
12 A 1 01/01/2013 Active
13 B 12 01/01/2013 Inactive
14 C 245 01/01/2013 Complete
BatchDetailID BatchID Weight Price DestinationCode
1 12 55 500.00 99
2 12 119 1500.00 55
3 13 12 133 1212
批记录可以通过FK BatchDetail.BatchID
链接许多批次明细记录我想编写一个查询来选择返回给用户的单行,该行将BATCH记录中的信息与BATCLDETAIL记录中的Weight,Price和DestinationCode结合起来,用于BatchID = 12
所以输出结果为:
BatchID Name CustomerID DateCreated Status WeightA PriceA DestinationCodeA WeightB PriceB DestinationCodeB
12 A 1 01/01/2013 Active 55 500.00 99 119 1500 55
所以你可以看到我希望有一行将所有信息组合在一行中,并用A或B区分每个细节记录(假设最多只允许2条细节记录)
我想过用这些字段创建一个表,然后在一系列select语句中构建信息,最后在临时表上进行选择,但是将查询放到单个SQL块中是理想的。
答案 0 :(得分:0)
以下是使用动态SQL的解决方案:
-- Get the MAX total number of records per BatchID (how many sets of columns do we need?)
DECLARE @requiredLevels int = (SELECT MAX(C) FROM (SELECT COUNT(*) C FROM BATCHDETAIL GROUP BY BatchID) Q)
;
-- Build a dynamic statement for the final SELECT fields
DECLARE
@finalFieldsSQL varchar(1000) = ''
, @finalFieldsN int = 1
;
WHILE @finalFieldsN <= @requiredLevels
BEGIN
SET @finalFieldsSQL = @finalFieldsSQL + ', Weight' + CHAR(64 + @finalFieldsN) + ', Price' + CHAR(64 + @finalFieldsN) + ', DestinationCode' + CHAR(64 + @finalFieldsN)
SET @finalFieldsN = @finalFieldsN + 1
END
-- Build a dynamic statement for the subquery SELECT fields
DECLARE
@subqueryFieldsSQL varchar(1000) = ''
, @subqueryFieldsN int = 1
;
WHILE @subqueryFieldsN <= @requiredLevels
BEGIN
SET @subqueryFieldsSQL = @subqueryFieldsSQL + ', MAX([' + CAST(@subqueryFieldsN AS varchar) + ']) ColumnName' + CHAR(64 + @subqueryFieldsN)
SET @subqueryFieldsN = @subqueryFieldsN + 1
END
-- Build a dynamic statement for the PIVOT fields
DECLARE
@pivotFieldsSQL varchar(1000) = ''
, @pivotFieldsN int = 1
;
WHILE @pivotFieldsN <= @requiredLevels
BEGIN
SET @pivotFieldsSQL = @pivotFieldsSQL + ', [' + CAST(@pivotFieldsN AS varchar) + ']'
SET @pivotFieldsN = @pivotFieldsN + 1
END
SET @pivotFieldsSQL = SUBSTRING(@pivotFieldsSQL, 3, LEN(@pivotFieldsSQL) - 2)
-- Build the final SQL statement and execute
DECLARE @SQL varchar(8000) =
'
SELECT
B.BatchID, B.Name, B.CustomerID, B.DateCreated, [Status]' + @finalFieldsSQL + '
FROM
BATCH B
LEFT JOIN
(
SELECT
BatchID' + REPLACE(@subqueryFieldsSQL, 'ColumnName', 'Weight') + '
FROM
(
SELECT BD.BatchID, [Weight], ROW_NUMBER() OVER (PARTITION BY B.BatchID ORDER BY BatchDetailID) R
FROM
BATCH B
JOIN BATCHDETAIL BD ON B.BatchID = BD.BatchID
) Q
PIVOT
(
MAX([Weight])
FOR R IN (' + @pivotFieldsSQL + ')
) P
GROUP BY BatchID
) W
ON B.BatchID = W.BatchID
LEFT JOIN
(
SELECT
BatchID' + REPLACE(@subqueryFieldsSQL, 'ColumnName', 'Price') + '
FROM
(
SELECT BD.BatchID, Price, ROW_NUMBER() OVER (PARTITION BY B.BatchID ORDER BY BatchDetailID) R
FROM
BATCH B
JOIN BATCHDETAIL BD ON B.BatchID = BD.BatchID
) Q
PIVOT
(
MAX(Price)
FOR R IN (' + @pivotFieldsSQL + ')
) P
GROUP BY BatchID
) P
ON B.BatchID = P.BatchID
LEFT JOIN
(
SELECT
BatchID' + REPLACE(@subqueryFieldsSQL, 'ColumnName', 'DestinationCode') + '
FROM
(
SELECT BD.BatchID, DestinationCode, ROW_NUMBER() OVER (PARTITION BY B.BatchID ORDER BY BatchDetailID) R
FROM
BATCH B
JOIN BATCHDETAIL BD ON B.BatchID = BD.BatchID
) Q
PIVOT
(
MAX(DestinationCode)
FOR R IN (' + @pivotFieldsSQL + ')
) P
GROUP BY BatchID
) D
ON B.BatchID = D.BatchID
'
EXEC (@SQL)
如果您不想显示空记录,请在最终声明(3次出现)中将LEFT JOIN
替换为JOIN
。
答案 1 :(得分:0)
您可以使用Pivot
和UnPivot
来实现此结果。试试这样的事情:
SELECT
BatchID,[Name],[CustomerID],[DateCreated],[Status],
MAX(Weight1) as WeightA,
MAX(Price1) as PriceA,
MAX(DestinationCode1) as DestinationCodeA,
MAX(Weight2) as WeightB,
MAX(Price2) as PriceB,
MAX(DestinationCode2) as DestinationCodeB
FROM (
SELECT *,COL + CAST(DENSE_RANK() OVER (PARTITION BY Batchid ORDER BY BatchDetailID ASC) AS VARCHAR) AS BATCHPIVOT
FROM
(
SELECT b.*,cast(d.Weight as varchar(255)) as Weight, cast(d.Price as varchar(255)) as Price, cast(d.DestinationCode as varchar(255)) as DestinationCode,d.BatchDetailID
FROM #Batch B
INNER JOIN #BATCHDETAIL D on b.BatchID = d.BatchID
) AS cp
UNPIVOT
(
Val FOR Col IN ([Weight], [Price], [DestinationCode])
) AS up
) AS query
PIVOT (MAX(Val)
FOR BATCHPIVOT IN (Weight1,Price1,DestinationCode1, Weight2, Price2, DestinationCode2)) AS Pivot1
GROUP BY BatchID,[Name],[CustomerID],[DateCreated],[Status]
这只是标准查询。你可以根据自己的喜好使这个脚本动态化:
完整脚本:
Create table #Batch
(BatchID int,
[Name] char(1),
[CustomerID] int,
[DateCreated] date,
[Status] varchar(50)
)
Create table #BATCHDETAIL
(BatchDetailID int,
BatchID int,
[Weight] int,
Price money,
DestinationCode int
)
INSERT INTO #Batch
VALUES(12,'A',1,'01/01/2013','Active')
,(13,'B',12,'01/01/2013','Inactive')
,(14,'C',245,'01/01/2013','Complete')
INSERT INTO #BATCHDETAIL
VALUES(1,12,55,500.00,99)
,(2,12,119,1500.00,55)
,(3,13,12,133,1212)
SELECT
BatchID,[Name],[CustomerID],[DateCreated],[Status],
MAX(Weight1) as WeightA,
MAX(Price1) as PriceA,
MAX(DestinationCode1) as DestinationCodeA,
MAX(Weight2) as WeightB,
MAX(Price2) as PriceB,
MAX(DestinationCode2) as DestinationCodeB
FROM (
SELECT *,COL + CAST(DENSE_RANK() OVER (PARTITION BY Batchid ORDER BY BatchDetailID ASC) AS VARCHAR) AS BATCHPIVOT
FROM
(
SELECT b.*,cast(d.Weight as varchar(255)) as Weight, cast(d.Price as varchar(255)) as Price, cast(d.DestinationCode as varchar(255)) as DestinationCode,d.BatchDetailID
FROM #Batch B
INNER JOIN #BATCHDETAIL D on b.BatchID = d.BatchID
) AS cp
UNPIVOT
(
Val FOR Col IN ([Weight], [Price], [DestinationCode])
) AS up
) AS query
PIVOT (MAX(Val)
FOR BATCHPIVOT IN (Weight1,Price1,DestinationCode1, Weight2, Price2, DestinationCode2)) AS Pivot1
GROUP BY BatchID,[Name],[CustomerID],[DateCreated],[Status]