Sql 变换这张桌子。类似于;coalasce“;至于;按“分组”;?
假设我有下表(id_a,id_b,type实际上是整数,数据实际上是xml): id_a、id_b和类型的组合是唯一的。 现在,我编写的一个程序得到一个我关心的类型列表作为输入。假设此列表包含X和Y。现在我想做一些SQL魔术,结果如下: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 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的解决方案之间的艰难决定。现在我选择了你的:-)。