Oracle将行转换为列

时间:2017-06-13 12:45:32

标签: sql oracle

我有一个看起来像这样的表:

station     node        group
13859160    13195576    high
13859160    42502030    low
13859165    42283197    low
13859165    42283198    high
13859166    13190800    low
13859166    13190801    low
13859166    13195587    high

可以使用以下语句创建:

CREATE TABLE nodes
    ("station" int, "node" int, "group" varchar(6))
;

并填写了这句话:

insert into nodes values (13859160, 13195576,   'high');
insert into nodes values (13859160, 42502030,   'low');
insert into nodes values (13859165, 42283197,   'low');
insert into nodes values (13859165, 42283198,   'high');
insert into nodes values (13859166, 13190800,   'low');
insert into nodes values (13859166, 13190801,   'low');
insert into nodes values (13859166, 13195587,   'high');

我想查询此表,以便高和低成为列,因此结果如下所示:

Station     high        low
13859160    13195576    42502030
13859165    42283198    42283197
13859166    13195587    13190801
13859166    13195587    13190800

如果那里没有多个“低”行的电台,那就很容易了,我可以做这样的事情来获得高点和低点:

select 
    "station",
    case when "group" = 'high' then "node" end as high,
    case when "group" = 'low' then "node" end as low
from "NODES";

导致:

enter image description here

然后使用聚合函数获取结果,如:

select 
    "station",
    max(case when "group" = 'high' then "node" end) as high,
    max(case when "group" = 'low' then "node" end) as low
from "NODES"
group by "station";

这导致:

enter image description here

但是,当1个startion有多个“low”enties时,我需要为每个低项创建一行,该行应该在两行中包含该站的相同“高”条目。

知道怎么做到这一点?

2 个答案:

答案 0 :(得分:0)

您可以使用条件聚合执行此操作。

select * from (
select 
    "station",
    max(case when "group" = 'high' then "node" end) over(partition by "station") as high,
    case when "group" = 'low' then "node" end as low
from nodes
) n
where low is not null

答案 1 :(得分:0)

首先,我可能会建议listagg()进行聚合查询:

select "station",
       listagg(case when "group" = 'high' then "node" end) as high,
       listagg(case when "group" = 'low' then "node" end) as low
from "NODES"
group by "station";

要为单个工作站获取多行,您可以使用row_number()

select "station",
       max(case when "group" = 'high' then "node" end) as high,
       max(case when "group" = 'low' then "node" end) as low
from (select n.*,
             row_number() over (partition by "station", "group" order by "node") as seqnum
      from "NODES" n
     ) n
group by "station", seqnum;

最后,如果您想要重复上一个最大值:

select "station",
       coalesce(max(case when "group" = 'high' then "node" end),
                max(max(case when "group" = 'high' then "node" end)) over (partition by "station)
               ) as high,
       max(case when "group" = 'low' then "node" end) as low
from (select n.*,
             row_number() over (partition by "station", "group" order by "node") as seqnum
      from "NODES"
     ) n
group by "station", seqnum;