过去(here和here)对此主题做出了非常好的答案。看来我仍然无法让我知道这个枢轴的东西(我也没用过很长时间)。
所以希望有人(再次)能够告诉我如何将数据转换为所需的格式:
鉴于数据:
ID | Label | Occurences | RangeBegin | RangeEnd | Unit
---+-------+------------+------------+----------+--------
1 | One | 0 | -1000 | 0 | m
1 | One | 5 | 0 | 10 | m
1 | One | 8 | 10 | 20 | m
1 | One | 6 | 20 | 30 | m
1 | One | 15 | 30 | 40 | m
1 | One | 0 | 40 | 1000 | m
2 | One | 0 | -1000 | 0 | m
2 | One | 2 | 0 | 10 | m
2 | One | 13 | 10 | 20 | m
2 | One | 27 | 20 | 30 | m
2 | One | 5 | 30 | 40 | m
2 | One | 0 | 40 | 1000 | m
1 | Two | 0 | -1000 | 0 | kg
1 | Two | 4 | 0 | 2 | kg
1 | Two | 6 | 2 | 4 | kg
1 | Two | 1 | 4 | 6 | kg
1 | Two | 0 | 6 | 1000 | kg
2 | Two | 0 | -1000 | 0 | kg
2 | Two | 8 | 0 | 2 | kg
2 | Two | 1 | 2 | 4 | kg
2 | Two | 3 | 4 | 6 | kg
2 | Two | 0 | 6 | 1000 | kg
期望的结果:
ID | One | OneRangeBegin | OneRangeEnd | OneUnit | Two | TwoRangeBegin | TwoRangeEnd | TwoUnit
---+-----+---------------+-------------+---------+------+---------------+-------------+----------
1 | 0 | -1000 | 0 | m | 0 | -1000 | 0 | kg
1 | 5 | 0 | 10 | m | 4 | 0 | 2 | kg
1 | 8 | 10 | 20 | m | 6 | 2 | 4 | kg
1 | 6 | 20 | 30 | m | 1 | 4 | 6 | kg
1 | 15 | 30 | 40 | m | 0 | 6 | 1000 | kg
1 | 0 | 40 | 1000 | m | null | null | null | null
2 | 0 | -1000 | 0 | m | 0 | -1000 | 0 | kg
2 | 2 | 0 | 10 | m | 8 | 0 | 2 | kg
2 | 13 | 10 | 20 | m | 1 | 2 | 4 | kg
2 | 27 | 20 | 30 | m | 3 | 4 | 6 | kg
2 | 5 | 30 | 40 | m | 0 | 6 | 1000 | kg
2 | 0 | 40 | 1000 | m | null | null | null | null
为了使其工作更容易,我将上面的数据放在SqlFiddle。
答案 0 :(得分:2)
我认为可以通过这样做来实现:
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY RangeBegin)
SELECT
A.ID AS ID
,A.Occurences AS One
,A.RangeBegin AS OneRangeBegin
,A.RangeEnd AS OneRangeEnd
,A.Unit AS OneUnit
,B.Occurences AS Two
,B.RangeBegin AS TwoRangeBegin
,B.RangeEnd AS TwoRangeEnd
,B.Unit AS TwoUnit
FROM
(select
*, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY RangeBegin) Rank
from
AvailableData
wHere Label = 'One') A
FULL JOIN
(select
*, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY RangeBegin) Rank
from
AvailableData
Where Label = 'Two' ) B
ON A.ID = B.ID
AND A.Rank = B.Rank
ORDER BY ISNULL(A.ID, B.ID), ISNULL(A.Rank, B.Rank)
答案 1 :(得分:1)
我总是很难绕着枢轴缠绕我的头。出于这个原因,我倾向于使用聚合CASE方法而不是PIVOT,因为我发现它更容易推理(并且它更灵活)。基本上你需要将你的问题分解为多个步骤。
聚合CASE枢轴的总体布局如下:
SELECT
grouped columns
,MAX(CASE WHEN condition THEN column END) as ColumnName
,...
FROM
Table
GROUP BY grouped columns
关键是上述条件将识别每列的来源。例如,当OneUnit
列为Unit
时,列Label
显然来自One
列,因此可能是:
MAX(CASE WHEN Label='One' THEN Unit END) as OneUnit
这很容易应用于您的特定示例,除非没有明显的方法将行从One关联到两个,因为您将不同的范围组合在一起。您需要确定一个明确的规则,以便在构建实际的数据透视查询之前将数据中的行组合在一起,这应该非常简单(这会生成额外的行,因为一个和两个集合之间的范围不同):
select
D.ID, D.RangeBegin, D.RangeEnd
,MAX(CASE WHEN Label='One' THEN D.Occurences END) as One
,MAX(CASE WHEN Label='One' THEN D.RangeBegin END) as OneRangeBegin
,MAX(CASE WHEN Label='One' THEN D.RangeEnd END) as OneRangeEnd
,MAX(CASE WHEN Label='One' THEN D.Unit END) as OneUnit
,MAX(CASE WHEN Label='Two' THEN D.Occurences END) as Two
,MAX(CASE WHEN Label='Two' THEN D.RangeBegin END) as TwoRangeBegin
,MAX(CASE WHEN Label='Two' THEN D.RangeEnd END) as vRangeEnd
,MAX(CASE WHEN Label='Two' THEN D.Unit END) as TwoUnit
from
AvailableData D
group by
D.ID, D.RangeBegin, D.RangeEnd