简体   繁体   English

没有已知列名的数据透视

[英]Pivoting without known column name

I have the following table with data: 我有带有数据的下表:

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

Now I need a PIVOT (?) query to: 现在,我需要一个PIVOT(?)查询来:

  • Group by column A. 按A列分组。
  • Sort on column B. 在B列上排序。
  • Take the lowest 3 values from column B. 从B列中选取最低的3个值。
  • Put these values in the new columns B1, B2, B3 将这些值放在新的列B1,B2,B3中

So the result will be: 因此结果将是:

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

So far I have been trying to create queries with TOP, GROUP BY, PIVOT. 到目前为止,我一直在尝试使用TOP,GROUP BY,PIVOT创建查询。 I think the best way to go is with the PIVOT, but since I do not have a value I can use as a column name, I am stuck. 我认为最好的方法是使用PIVOT,但是由于我没有值可以用作列名,因此我陷入了困境。 Also, making a top-3 selection of these values seems also pretty challenging. 同样,对这些值进行前三项选择似乎也很有挑战性。

* EDIT * *编辑*

Their is a unique constraint on columns A and B, so the values for B are always unique for the same A. 它们是对列A和B的唯一约束,因此对于相同的A,B的值始终是唯一的。

You can use the PIVOT function to get the result, but I would also implement a windowing function similar to row_number() to get the final result. 您可以使用PIVOT函数获取结果,但是我还将实现类似于row_number()的窗口函数以获取最终结果。 The row_number() function will create a unique sequenced number for each B value if you partition the data over the A column. 如果将数据划分到A列上,则row_number()函数将为每个B值创建一个唯一的序列号。 This sequenced number will be used as the new column names: 该序列号将用作新的列名:

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;

See SQL Fiddle with Demo . 请参阅带有演示的SQL Fiddle This will give a result: 这将产生结果:

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

Here is an approach that works with both Oracle and SQL Server (the original question was tagged with both databases). 这是一种适用于Oracle和SQL Server的方法(两个数据库都标记了原始问题)。

You can just enumerate the b values for each a using dense_rank() (or row_number() , but dense_rank() will give three different values if there are duplicates). 您可以使用dense_rank()row_number()枚举每个ab值,但如果有重复项,则dense_rank()将给出三个不同的值)。 Then pivot using conditional aggregation: 然后使用条件聚合进行透视:

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;

EDIT: 编辑:

The question is unclear on what to do if there are duplicates. 问题是如果有重复该怎么办尚不清楚。 For instance, if the data in b is 1, 1, 2, 3. Which should be the three columns? 例如,如果b的数据是b 。那三列应该是哪一列?

1, 2, 3

or 1, 1, 2 或1,1,2

The use of dense_rank() puts three different values into the columns (the first possible result). 使用dense_rank()将三个不同的值放入列中(第一个可能的结果)。 The use of row_number() would put the three smallest values (the second result). 使用row_number()将放置三个最小值(第二个结果)。 If there are never any duplicate values, then dense_rank() and row_number() produce the same results. 如果从不存在任何重复值,那么dense_rank()row_number()产生相同的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM