有关为每个
Price
和 ProductGroupID
组合选择最新 PersonID
的逻辑,请参阅获取每组的前 1 行。一般技术是使用 ROW_NUMBER()
窗口函数 对每组内的行进行编号,然后筛选 row-number = 1。
完成后,只需执行 PIVOT 操作即可。
SELECT PVT.[GROUP C], PVT.[GROUP B], PVT.[GROUP A], PVT.FullName, PVT.PersonId
FROM (
SELECT PG.ProductGroupName, PGP.Price, P.FullName, P.PersonId
FROM (
SELECT
*,
ROW_NUMBER()
OVER(PARTITION BY ProductGroupID, PersonID ORDER BY PriceDate DESC)
AS RowNum
FROM ProductGroupPrice
) PGP
JOIN ProductGroup PG
ON PG.ProductGroupID = PGP.ProductGroupID
JOIN person P
ON P.PersonID = PGP.PersonID
WHERE PGP.RowNum = 1
) Q
PIVOT (
MAX(Q.Price)
FOR Q.ProductGroupName IN ([GROUP C], [GROUP B], [GROUP A])
) PVT
ORDER BY PVT.PersonId
使用
PIVOT
的替代方法是 条件聚合,您可以在其中定义像 MAX(CASE WHEN <condition> THEN <value> END) AS <column>
这样的选择项。
SELECT
MAX(CASE WHEN PG.ProductGroupName = 'GROUP C' THEN PGP.Price END) AS [GROUP C],
MAX(CASE WHEN PG.ProductGroupName = 'GROUP B' THEN PGP.Price END) AS [GROUP B],
MAX(CASE WHEN PG.ProductGroupName = 'GROUP A' THEN PGP.Price END) AS [GROUP A],
P.FullName,
P.PersonId
FROM (
SELECT
*,
ROW_NUMBER()
OVER(PARTITION BY ProductGroupID, PersonID ORDER BY PriceDate DESC)
AS RowNum
FROM ProductGroupPrice
) PGP
JOIN ProductGroup PG
ON PG.ProductGroupID = PGP.ProductGroupID
JOIN person P
ON P.PersonID = PGP.PersonID
WHERE PGP.RowNum = 1
GROUP BY P.FullName, P.PersonId
ORDER BY P.PersonId
中间结果:
产品组名称 | 价格 | 全名 | 人员ID |
---|---|---|---|
A组 | 250 | 卡雷尔 | 1 |
A组 | 120 | 阿里 | 3 |
A组 | 100 | 埃姆兰 | 4 |
B组 | 150 | 卡雷尔 | 1 |
B组 | 200 | 杰克 | 2 |
C组 | 150 | 卡雷尔 | 1 |
C组 | 100 | 杰克 | 2 |
C组 | 105 | 哈娜 | 5 |
最终结果:
C组 | B组 | A组 | 全名 | 人员ID |
---|---|---|---|---|
150 | 150 | 250 | 卡雷尔 | 1 |
100 | 200 | 空 | 杰克 | 2 |
空 | 空 | 120 | 阿里 | 3 |
空 | 空 | 100 | 埃姆兰 | 4 |
105 | 空 | 空 | 哈娜 | 5 |
请参阅 this db<>fiddle 了解两种方法的演示。
您可以使用 PIVOT 来获取一次查询的结果
select
isnull(MAX([Group C]),'') as [Group C]
, isnull(MAX([Group B]),'') as [Group B]
, isnull(MAX([Group A]),'') as [Group A]
,FullName, PersonID
from
(
SELECT PGP.*, P.FullName, PG.ProductGroupName, CONVERT(varchar(10),Pricedate,112) + '-' + Price as DatePrice
FROM ProductGroupPrice PGP
INNER JOIN ProductGroup PG ON PG.ProductGroupID=PGP.ProductGroupID
INNER JOIN person P ON P.PersonID=PGP.PersonID
) x
pivot
(
max(DatePrice)
for ProductGroupName in([Group A], [Group B], [Group C])
)p
GROUP BY FullName, PersonID