转换此表。对于“Group by”有类似“coalasce”的东西?

时间:2011-07-22 14:07:25

标签: sql db2

假设我有下表(id_a,id_b,类型实际上是整数,数据实际上是xml):

id_a   id_b    type     data
-----+------+--------+--------
  1     1       X        X1
  1     1       Y        Y1
  7    17       Y        Y2
  7    99       X        X2
  9    20       Z        Z1

id_a,id_b和type的组合是唯一的。 现在,我编写的程序将输入一个我关心的类型列表作为输入。假设此列表包含X和Y.现在我想做一些最终得到以下结果的SQL-Magic:

id_a   id_b      X        Y
-----+------+--------+--------
  1      1      X1        Y1
  7      17     NULL      Y2
  7      99     X2        NULL

单词:我想要一行包含id_a和id_b的所有数据,列出数据列。

我能够自己找到一个查询,最终得到下表:

table:
id_a   id_b   data_x   data_y
-----+------+--------+--------
  1     1       X1      NULL
  1     1       NULL       Y1
  7    17       NULL       Y2
  7    99       X2       NULL

查询:

select
  id_a,
  id_b,
  case when type = 'X' then data
  end data_x,
  case when type = 'Y' then data
  end data_y,
from
  mytable
order by
  id_a,id_b

在此表中保证

  • 最多只有一个data_x或data_y可能是非NULL(两个NULL也可以,但当然可以通过where data_x is not null or data_y is not null轻松过滤)
  • data_x和data_y对于id_a和id_b的组合都是唯一的。

如果我现在可以做select coalesce(case ... data_y),coalesce(case ... data_y) from ... group by id_a,id_b那么我相信我会成为我想去的地方,但不幸的是,coalesce不是一个聚合函数,而是一个标量函数。

在我的客户端应用程序(用Java编写)中,我当然可以迭代行,合并行,但这看起来不是很优雅;-)。是否有“漂亮”的方法来解决这个问题?

我使用的是DB2 V9.7,但我更喜欢便携式解决方案......

3 个答案:

答案 0 :(得分:2)

使用MAX?

SELECT
  id_a,
  id_b,
  MAX(CASE WHEN type = 'X' THEN data END) AS data_x,
  MAX(CASE WHEN type = 'Y' THEN data END) AS data_y
FROM
  myTable
GROUP BY
  id_a,
  id_b

修改

如果你不能使用聚合函数,这样的东西是否适合你的需要?

SELECT
  map.id_a,
  map.id_b,
  myTableX.data AS data_x,
  myTableY.data AS data_y
FROM
  (SELECT id_a, id_b FROM myTable GROUP BY id_a, id_b) AS map
LEFT JOIN
  myTable AS myTableX
    ON  myTalbeX.id_a = map.id_a
    AND myTableX.id_b = map.id_b
    AND myTableX.type = 'X'
LEFT JOIN
  myTable AS myTableY
    ON  myTalbeY.id_a = map.id_a
    AND myTableY.id_b = map.id_b
    AND myTableY.type = 'Y'

答案 1 :(得分:1)

这会得到您想要的结果:

create table myTable (
    id_a int not null,
    id_b int not null,
    type char(1) not null,
    data varchar(10),
    unique (id_a, id_b, type)
);

insert into myTable values (1, 1, 'X', 'X1');
insert into myTable values (1, 1, 'Y', 'Y1');
insert into myTable values (7, 17, 'Y', 'Y2');
insert into myTable values (7, 99, 'X', 'X2');
insert into myTable values (9, 20, 'Z', 'Z1');

select coalesce(X.id_a, Y.id_a) as id_a, coalesce(X.id_b, Y.id_b) as id_b, 
        X.data as X, Y.data as Y
    from (select * from myTable where type = 'X') X 
        full outer join (select * from myTable Y where type = 'Y') Y 
            on X.id_a = Y.id_a and X.id_b = Y.id_b

结果

 ID_A ID_B X    Y
 ---- ---- ---- ----
    1    1 X1   Y1
    7   17 NULL Y2
    7   99 X2   NULL

答案 2 :(得分:0)

您仍需要做一些事情,将出现在不同记录中的数据放入结果集的同一记录中。为此,您需要使用聚合函数,例如最大,最小我无权访问DB2,但在许多方面它与Oracle非常相似。以下在Oracle上运行得很好。

with tmp as 
 (select 1 id_a, 1  id_b, 'X' type_, 'X1' data_ from dual union
  select 1 id_a, 1  id_b, 'Y' type_, 'Y1' data_ from dual union
  select 7 id_a, 17 id_b, 'Y' type_, 'Y2' data_ from dual union
  select 7 id_a, 99 id_b, 'X' type_, 'X2' data_ from dual union
  select 9 id_a, 20 id_b, 'Z' type_, 'Z1' data_ from dual)
select distinct 
       id_a, 
       id_b,
       max(decode(type_, 'X', data_, null)) data_x,
       max(decode(type_, 'Y', data_, null)) data_y  
  from tmp  
 group by id_a, id_b  

修改 对于非聚合版本,您可以使用:

    with tmp as 
     (select 1 id_a, 1  id_b, 'X' type_, 'X1' data_ from dual union
      select 1 id_a, 1  id_b, 'Y' type_, 'Y1' data_ from dual union
      select 7 id_a, 17 id_b, 'Y' type_, 'Y2' data_ from dual union
      select 7 id_a, 99 id_b, 'X' type_, 'X2' data_ from dual union
      select 9 id_a, 20 id_b, 'Z' type_, 'Z1' data_ from dual)
    select nvl(x.id_a, y.id_a) id_a, nvl(x.id_b, y.id_b) id_b, x.data_, y.data_ 
      from tmp x
           full outer join tmp y
             on (    x.id_a = y.id_a
                 and x.id_b = y.id_b
                 and x.type_ = 'X'
                 and y.type_ = 'Y')
 where x.data_ like 'X%' or  y.data_ like 'Y%'