2015-09-04 72 views
-1

过去已经很好地回答了这个问题(herehere)。看来,我仍然无法让我知道这个关键的东西(我也没有使用它很长一段时间)。如何在SQL Server 2008中透视数据以获得期望的结果?

所以希望有人(再次)能告诉我如何将数据放到所需的格式:

鉴于数据:

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

+1

两个表你需要看看逆转置和支点。你有没有尝试过任何代码来获得解决方案? – Taryn

+1

发布您的查询尝试,并发现它出了什么问题。错误或意外结果? –

回答

2

我认为它可以做这样的事情来实现:

  1. 拆表基于标签
  2. 排名上标识的每个表的分区和基于RangeBegin安排它。ROW_NUMBER() OVER(PARTITION BY ID ORDER BY RangeBegin)
  3. 全部加入的ID和排名

SQL Fiddle

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

我一直有困难缠绕枢轴以及我的头。出于这个原因,我倾向于使用聚合CASE方法而不是PIVOT,因为我觉得更容易推理(而且更灵活)。基本上你需要将问题分解成多个步骤。

  1. 确定如何将数据分组 - 例如,通过ID,RangeBegin,rangeEnd的
  2. 确定所有列将是什么,他们将在那里进行采购
  3. 写的聚合CASE语句每一列 - 注意:您必须确保每个输出是明确的,或者你会得到缺失的结果

聚合CASE枢纽的总体布局是这样的:

SELECT 
    grouped columns 
    ,MAX(CASE WHEN condition THEN column END) as ColumnName 
    ,... 
FROM 
    Table 
GROUP BY grouped columns 

关键是上述条件将确定每列的来源。因此,例如,列OneUnit显然来自于Unit列当LabelOne,所以这将是:

MAX(CASE WHEN Label='One' THEN Unit END) as OneUnit 

这将是很容易申请到您的具体的例子,但没有明显的将One到Two的行关联在一起,因为您将不同的范围组合在一起。您需要确定一个明确的规则,以便在构建实际的数据透视查询之前将各行组合在一起,这应该非常简单(由于一组和两组之间的范围不同,因此当前会生成额外的行):

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 
相关问题