没有已知列名称的透视

时间:2013-12-16 14:56:48

标签: sql oracle pivot

我的数据包含下表:

A   B
=== ===
M   2  
M   3
M   5
N   5
N   2
O   6
P   13
P   7
P   9
P   11
P   3

现在我需要一个PIVOT(?)查询:

  • 按A栏分组。
  • 按B列排序。
  • 从B列中取出最低的3个值。
  • 将这些值放在新列B1,B2,B3

结果将是:

A   B1   B2   B3
=== ==== ==== ====
M   2    3    5
N   2    5    null
O   6    null null
P   3    7    9

到目前为止,我一直在尝试使用TOP,GROUP BY,PIVOT创建查询。我认为最好的方法是使用PIVOT,但由于我没有值,我可以用作列名,我被卡住了。此外,对这些值进行前3选择似乎也非常具有挑战性。

*编辑*

它们是A列和B列的唯一约束,因此B的值对于相同的A始终是唯一的。

2 个答案:

答案 0 :(得分:7)

你可以使用PIVOT函数来获得结果,但我也会实现类似于row_number()的窗口函数来获得最终结果。如果您在row_number()列上对数据进行分区,则B函数会为每个A值创建唯一的序列号。此序列号将用作新列名:

select a, B1, B2, B3
from
(
  select a, b,
    row_number() over(partition by a
                      order by b) seq
  from yourtable
) d
pivot
(
  max(b)
  for seq in ('1' as B1, '2' as B2, '3' as B3)
) piv;

SQL Fiddle with Demo。这将得到一个结果:

| A | B1 |     B2 |     B3 |
|---|----|--------|--------|
| M |  2 |      3 |      5 |
| N |  2 |      5 | (null) |
| O |  6 | (null) | (null) |
| P |  3 |      7 |      9 |

答案 1 :(得分:4)

这是一种适用于Oracle和SQL Server的方法(原始问题已用两个数据库标记)。

您可以使用b(或a枚举每个dense_rank()的{​​{1}}值,但如果有重复,row_number()会给出三个不同的值)。然后使用条件聚合进行调整:

dense_rank()

编辑:

如果有重复,该问题不明确该怎么办。例如,如果with ab as ( select a, b, dense_rank() over (partition by a order by b asc) as seqnum from t ) select a, max(case when seqnum = 1 then b end) as b1, max(case when seqnum = 2 then b end) as b2, max(case when seqnum = 3 then b end) as b3 from ab group by a; 中的数据是1,1,3,3。这应该是三列?

b

或     1,1,2

1, 2, 3 的使用将三个不同的值放入列中(第一个可能的结果)。 dense_rank()的使用将放置三个最小值(第二个结果)。如果从未有任何重复值,则row_number()dense_rank()会产生相同的结果。