在没有已知列名的情况下进行透视

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 函数的情况下进行透视?

Django,将模型类导入新文件。导入错误尝试在没有已知父项的情况下进行相对导入

在没有聚合的情况下在 SQL 中透视表