合并行以创建两列数据
Combining rows to create two columns of data
我对如何正确执行此查询有点困惑。我有一个看起来像这样的 table。其中0区代表一个值,应该应用到所有区(全局)。
[ district ] [ code ] [ value ]
1 A 11
1 C 12
2 A 13
2 B 14
0 B 15
我已经建立了一个查询(如下)来合并每个地区的 "global value"。
[ district ] [ code ] [ district value ] [ global value ]
1 A 11 null -> row 1
1 B null 15 -> row 2
1 C 12 null -> row 3
2 A 13 null -> row 4
2 B 14 15 -> row 5
2 C null null -> row 6 (optional)
我加入了所有可能的列表 district/code。
select all_code.district, all_code.code, table_d.value, table_g.value
from (select distinct b.district, a.code
from temp_table a
inner join (select distinct district
from temp_table
where district <> 0) b
on 1 = 1) all_code
left join temp_table table_d
on table_d.code = all_code.code
and table_d.district = all_code.district
left join temp_table table_g
on table_g.code = all_code.code
and table_g.district = 0
这个查询很好用,但看起来很丑。有更好的方法吗? (请注意,我不关心第 6 行是否存在)。
如果需要,这里有一个脚本。
create table temp_table
(
district VARCHAR2(5) not null,
code VARCHAR2(5) not null,
value VARCHAR2(5) not null
);
insert into temp_table (district, code, value)
values ('1', 'A', '11');
insert into temp_table (district, code, value)
values ('1', 'C', '12');
insert into temp_table (district, code, value)
values ('2', 'A', '13');
insert into temp_table (district, code, value)
values ('2', 'B', '14');
insert into temp_table (district, code, value)
values ('0', 'B', '15');
这是其中一个选项。由于您使用的是 10g,因此您可以使用分区外连接(partition by()
子句)来填补空白:
with DCodes(code) as(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual
),
DGlobal(code, value1) as(
select code
, value
from temp_table
where district = 0
)
select tt.district
, dc.code
, tt.value
, dg.value1 as global_value
from temp_table tt
partition by(tt.district)
right join DCodes dc
on (dc.code = tt.code)
left join DGlobal dg
on (dg.code = dc.code)
where tt.district != 0
order by 1, 2
结果:
DISTRICT CODE VALUE GLOBAL_VALUE
-------- ---- ----- ------------
1 A 11
1 B 15
1 C 12
2 A 13
2 B 14 15
2 C
我认为很多 "ugliness" 是因为缺少 district
和 code
的查找表。如果没有这些的权威来源,您必须根据正在使用的值来制作一个(因此使用 distinct
的子查询)。
就清理您的查询而言,我能想到的最好办法是删除不必要的子查询并使用正确的交叉连接语法:
SELECT a.district,
b.code,
c.value1,
d.value1
FROM (SELECT DISTINCT district FROM temp_table WHERE district <> 0) a
CROSS JOIN (SELECT DISTINCT code FROM temp_table) b
LEFT JOIN temp_table c
ON b.code = c.code AND a.district = c.district
LEFT JOIN temp_table d
ON b.code = d.code AND d.district = 0
ORDER BY district, code
我对如何正确执行此查询有点困惑。我有一个看起来像这样的 table。其中0区代表一个值,应该应用到所有区(全局)。
[ district ] [ code ] [ value ]
1 A 11
1 C 12
2 A 13
2 B 14
0 B 15
我已经建立了一个查询(如下)来合并每个地区的 "global value"。
[ district ] [ code ] [ district value ] [ global value ]
1 A 11 null -> row 1
1 B null 15 -> row 2
1 C 12 null -> row 3
2 A 13 null -> row 4
2 B 14 15 -> row 5
2 C null null -> row 6 (optional)
我加入了所有可能的列表 district/code。
select all_code.district, all_code.code, table_d.value, table_g.value
from (select distinct b.district, a.code
from temp_table a
inner join (select distinct district
from temp_table
where district <> 0) b
on 1 = 1) all_code
left join temp_table table_d
on table_d.code = all_code.code
and table_d.district = all_code.district
left join temp_table table_g
on table_g.code = all_code.code
and table_g.district = 0
这个查询很好用,但看起来很丑。有更好的方法吗? (请注意,我不关心第 6 行是否存在)。
如果需要,这里有一个脚本。
create table temp_table
(
district VARCHAR2(5) not null,
code VARCHAR2(5) not null,
value VARCHAR2(5) not null
);
insert into temp_table (district, code, value)
values ('1', 'A', '11');
insert into temp_table (district, code, value)
values ('1', 'C', '12');
insert into temp_table (district, code, value)
values ('2', 'A', '13');
insert into temp_table (district, code, value)
values ('2', 'B', '14');
insert into temp_table (district, code, value)
values ('0', 'B', '15');
这是其中一个选项。由于您使用的是 10g,因此您可以使用分区外连接(partition by()
子句)来填补空白:
with DCodes(code) as(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual
),
DGlobal(code, value1) as(
select code
, value
from temp_table
where district = 0
)
select tt.district
, dc.code
, tt.value
, dg.value1 as global_value
from temp_table tt
partition by(tt.district)
right join DCodes dc
on (dc.code = tt.code)
left join DGlobal dg
on (dg.code = dc.code)
where tt.district != 0
order by 1, 2
结果:
DISTRICT CODE VALUE GLOBAL_VALUE
-------- ---- ----- ------------
1 A 11
1 B 15
1 C 12
2 A 13
2 B 14 15
2 C
我认为很多 "ugliness" 是因为缺少 district
和 code
的查找表。如果没有这些的权威来源,您必须根据正在使用的值来制作一个(因此使用 distinct
的子查询)。
就清理您的查询而言,我能想到的最好办法是删除不必要的子查询并使用正确的交叉连接语法:
SELECT a.district,
b.code,
c.value1,
d.value1
FROM (SELECT DISTINCT district FROM temp_table WHERE district <> 0) a
CROSS JOIN (SELECT DISTINCT code FROM temp_table) b
LEFT JOIN temp_table c
ON b.code = c.code AND a.district = c.district
LEFT JOIN temp_table d
ON b.code = d.code AND d.district = 0
ORDER BY district, code