我有一个表,该表必须根据状态连接到另一个表。这是表1数据的示例:
ROWID STATE
34 TX
56 NY
67 WA
89 TX
表1中的每一行都有状态值。表2每种状态都有两个记录。这是示例:
ROWID STATE NAME
19 TX Chuck, Brown
20 TX Nick, Johnes
如表2所示,德克萨斯州有两条记录。如果我使用Left Outer Join
并尝试执行以下操作:
LEFT OUTER JOIN Table 2 TB2
ON TB1.STATE = TB2.SATE
然后输出将是这样的:
34 TX Chuck, Brwon
34 TX Nick, Johnes
89 TX Chuck, Brwon
89 TX Nick, Johnes
每行都是重复的,因为表1中有两个针对得克萨斯州的记录。然后我在表2中有两个针对得克萨斯州的记录。我想看的是这样:
ROWID STATE NAME 1 NAME 2
34 TX Chuck, Brwon Nick, Johnes
基本上,我想将两行合并为一个,然后加入表1。我最近开始从事这个项目,我们使用Oracle数据库。如果有人知道实现此目标的好方法,请告诉我。谢谢。
答案 0 :(得分:1)
基于样本所需的输出,我将输出限制为表1中的第一个状态实例,并按ID对数据透视表名称进行了排序,尽管这恰好与给定示例数据的名称字段的alpha顺序匹配。 / p>
查看此SQL Fiddle
Oracle 11g R2架构设置:
请注意,在Oracle ROWID中是保留名称,因此我将其更改为ID。
CREATE TABLE Table1
("ID" number, "STATE" varchar2(2))
;
INSERT ALL
INTO Table1 ("ID", "STATE")
VALUES (34, 'TX')
INTO Table1 ("ID", "STATE")
VALUES (56, 'NY')
INTO Table1 ("ID", "STATE")
VALUES (67, 'WA')
INTO Table1 ("ID", "STATE")
VALUES (89, 'TX')
SELECT * FROM dual
;
CREATE TABLE Table2
("ID" number, "STATE" varchar2(2), "NAME" varchar2(12))
;
INSERT ALL
INTO Table2 ("ID", "STATE", "NAME")
VALUES (19, 'TX', 'Chuck, Brown')
INTO Table2 ("ID", "STATE", "NAME")
VALUES (20, 'TX', 'Nick, Johnes')
SELECT * FROM dual
;
查询1 :
select t1.id
, t2.state
, t2.name
from (select min(id) id, state from table1 group by state) t1
join table2 t2
on t1.state = t2.state
Results :
| ID | STATE | NAME |
|----|-------|--------------|
| 34 | TX | Nick, Johnes |
| 34 | TX | Chuck, Brown |
查询2 :
with t1(id, state) as (
select min(id) id, state from table1 group by state
), t2 as (
select state
, row_number() over (partition by state order by name) rn
, name
from table2
)
select t1.id
, pvt.*
from t1
join t2 pivot (max(name) for rn in (1 name_1,2 name_2)) pvt
on t1.state = pvt.state
Results :
| ID | STATE | NAME_1 | NAME_2 |
|----|-------|--------------|--------------|
| 34 | TX | Chuck, Brown | Nick, Johnes |
答案 1 :(得分:1)
在该问题下的一条评论中,您说您将接受一个单独的串联 NAME列,这是一个选择;我使用CTE创建表,因此您需要从第13行开始。
SQL> with
2 t1 (rid, state) as
3 (select 34, 'TX' from dual union all
4 select 56, 'NY' from dual union all
5 select 67, 'WA' from dual union all
6 select 89, 'TX' from dual
7 ),
8 t2 (rid, state, name) as
9 (select 19, 'TX', 'Chuck, Brown' from dual union all
10 select 20, 'TX', 'Nick, Johnes' from dual
11 ),
12 -- start here
13 it2 as
14 (select state, listagg(name, ' & ') within group (order by null) name
15 from t2
16 group by state
17 )
18 select min(t1.rid) rid,
19 t1.state,
20 it2.name
21 from t1 join it2 on t1.state = it2.state
22 and t1.state = 'TX'
23 group by t1.state, it2.name;
RID ST NAME
---------- -- ------------------------------
34 TX Chuck, Brown & Nick, Johnes
SQL>