在没有已知列名的情况下进行透视
Posted
技术标签:
【中文标题】在没有已知列名的情况下进行透视【英文标题】:Pivoting without known column name 【发布时间】:2013-12-16 14:56:48 【问题描述】:我有下表的数据:
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 始终是唯一的。
【问题讨论】:
您使用的是哪个数据库? Oracle 还是 SQL Server? 我正在使用 Oracle。我删除了不正确的标签。 @MartinMulder 您使用的是什么版本的 Oracle? 【参考方案1】:您可以使用 PIVOT 函数来获取结果,但我也会实现类似于row_number()
的窗口函数来获取最终结果。如果您在 A
列上对数据进行分区,row_number()
函数将为每个 B
值创建一个唯一的序列号。此序列号将用作新列名:
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 |
【讨论】:
【参考方案2】:这是一种适用于 Oracle 和 SQL Server 的方法(原始问题已标记为两个数据库)。
您可以只使用dense_rank()
(或row_number()
,但dense_rank()
将给出三个不同的值,如果有重复)为每个a
枚举b
值。然后使用条件聚合进行透视:
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;
编辑:
问题不清楚如果有重复该怎么办。比如b
中的数据是1、1、2、3,那三列应该是哪一列?
1, 2, 3
或 1、1、2
dense_rank()
的使用将三个不同的值放入列中(第一个可能的结果)。使用row_number()
将放置三个最小值(第二个结果)。如果从来没有任何重复值,那么dense_rank()
和row_number()
会产生相同的结果。
【讨论】:
DENSE_RANK
不能这样工作(至少在 SQL Server 中),如果有重复,它将给出相同的值。另一方面,ROW_NUMBER
会按照您的意愿行事
@Lamak 。 . .我的意思是如果有重复,dense_rank()
会给出三个不同的b
值。 row_number()
将重复 b
的值。目前尚不清楚 OP 想要什么。
是的,这就是我说的不对,dense_rank
会在重复的情况下返回相同的值而row_number
不会
@Lamak 。 . .假设你有 1、1、2、3。问题是:你想要 1、2、3 (dense_rank()
) 还是 (1, 1, 2) (row_number()
)。我将 OP 中的“最低 3 个值”解释为“最低 3 个不同的值”。知道为什么这会被否决吗?
@GordonLinoff 好的,我明白你现在在说什么,从你的解释中不清楚,你可以将它添加到你的答案中(这不是我的反对意见,但我认为这是分区) 以上是关于在没有已知列名的情况下进行透视的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 ImportError:尝试在没有已知父包的情况下进行相对导入
ImportError:尝试在没有已知父包的情况下进行相对导入(Python 3)
如何在不使用 SQL 中的 PIVOT 函数的情况下进行透视?