Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 变换这张桌子。类似于;coalasce“;至于;按“分组”;?_Sql_Db2 - Fatal编程技术网

Sql 变换这张桌子。类似于;coalasce“;至于;按“分组”;?

Sql 变换这张桌子。类似于;coalasce“;至于;按“分组”;?,sql,db2,Sql,Db2,假设我有下表(id_a,id_b,type实际上是整数,数据实际上是xml): id_a、id_b和类型的组合是唯一的。 现在,我编写的一个程序得到一个我关心的类型列表作为输入。假设此列表包含X和Y。现在我想做一些SQL魔术,结果如下: id_a id_b X Y -----+------+--------+-------- 1 1 X1 Y1 7 17 NULL Y2 7 99

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

id_a、id_b和类型的组合是唯一的。 现在,我编写的一个程序得到一个我关心的类型列表作为输入。假设此列表包含X和Y。现在我想做一些SQL魔术,结果如下:

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
本表保证:

  • 数据_x或数据_y中的一个最大值可能为非空(两个空值也可以,但这当然可以通过
    进行过滤,其中数据_x不为空或数据_y不为空
  • 对于id_a和id_b的组合,data_x和data_y都是唯一的
如果我现在可以做一个
选择coalesce(case…data_y),coalesce(case…data_y)from。。。按id_a,id_b分组,然后我相信我会在我想去的地方,但不幸的是,coalesce不是一个聚合函数,而是一个标量函数

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

我正在使用DB2V9.7,但我更喜欢一个可移植的解决方案…

使用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'
用马克斯

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'

您仍然需要做一些事情,将不同记录中出现的数据放入结果集的同一记录中。要做到这一点,您需要使用聚合函数,例如max、min。我没有访问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%'

您仍然需要做一些事情,将不同记录中出现的数据放入结果集的同一记录中。要做到这一点,您需要使用聚合函数,例如max、min。我没有访问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%'

这将提供您想要的结果:

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

这将提供您想要的结果:

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

好主意,但是:“每个参数必须是一个表达式,它返回除CLOB、DBCLOB、BLOB、ROWID或XML之外的任何内置数据类型的值”(DB2手册关于MAX)。不幸的是,我的“数据”列的类型是XML:-(.很好的解决方案,谢谢:-)。虽然我最终决定采用Frans的解决方案,但我认为两者都做得很好……我使用的是DB2,这是(修订后的答案)关于我将如何处理它——尽管我可能会使用CTE而不仅仅是表引用(主要是通过习惯的力量)。好主意,但是:“每个参数都必须是一个表达式,它返回除CLOB、DBCLOB、BLOB、ROWID或XML之外的任何内置数据类型的值”(关于MAX的DB2手册)。不幸的是,我的“数据”列的类型是XML:-(.nice solution,谢谢:-)。虽然我最终选择了Frans的解决方案,但我认为两者都做得很好……我使用的是DB2,这就是(修改后的答案)关于我将如何处理它-尽管我可能会使用CTE而不仅仅是表引用(主要是出于习惯)。是的,我需要一个聚合函数,但不幸的是,这与Dems的答案几乎相同。我不能使用max(),因为数据是XML类型。在修订后的anser中,您需要在完全外部联接之前将
tmp
表筛选为仅为“X”或仅为“Y”。目前,联接允许
tmp X
包含所有内容,然后根据谓词仅联接
tmp Y
。此外,where子句还消除
X的任何记录。data
y.data
NULL
。您好@Dems。您可能希望尝试按原样运行它。它对我来说效果很好。请注意,
tmp x
tmp y
的筛选仅为“x”或“y”出现在
on
子句的
中。是的,我需要一个聚合函数,但不幸的是非常好的与Dems的答案大致相同。我不能使用max(),因为数据是XML类型。在修订后的anser中,您需要在完全外部联接之前将
tmp
表筛选为仅为“X”或仅为“Y”。目前,联接允许
tmp X
包含所有内容,然后根据谓词仅联接
tmp Y
。此外,where子句还消除
X的任何记录。data
y.data
NULL
。您好@Dems。您可能想尝试按原样运行它。它对我来说效果很好。请注意,
tmp x
tmp y
的筛选仅为“x”或仅为“y”出现在
on
子句的
中。您的解决方案和Dems之间的决定非常明智,是……艰难解决方案。现在我选择了你的:-)。相当聪明,是的……你的解决方案和DEM的解决方案之间的艰难决定。现在我选择了你的:-)。