Oracle DB
Table1看起来如此,它是严格一对一的,没有重复......
Row Primary Secondary
--------------------------------
1 1 2
2 3 4
3 5 6
Table2具有相应的ID,每个ID都有多个名称。
ID Name
------------------------
1 Server1
2 Server2
3 Server3
3 Server4
3 Server5
4 Server6
4 Server7
5 Server8
6 Server9
6 Server10
现在,这就是我现在正在做的事情,简化......
Select t1.row row,
t2.name p_name,
t2a.name s_name
From table1 t1
left join table2 t2 on t1.primary = t2.id
left join table2 t2a on t1.secondary = t2a.id
这给了我这样的结果,我知道我使用的代码是正确的。
Row p_name s_name
-------------------------------
1 Server1 Server2
2 Server3 Server6
2 Server3 Server7
2 Server4 Server6
2 Server4 Server7
2 Server5 Server6
2 Server5 Server7
3 Server8 Server9
3 Server8 Server10
我想要什么,无法弄清楚怎么做...得到这个结果:
Row p_name s_name
-------------------------------
1 Server1 Server2
2 Server3 Server6
2 Server4 Server7
2 Server5 null
3 Server8 Server9
3 null Server10
本质上......我希望能够将值从1对1配对,其中每个值可以有1,2,3或更多,但我不想要所有组合,只是1,2或3,然后是另一组1,2或3,并且数字的空值不相等。我显然是SQL的新手并且已经四处寻找,我无法弄清楚下一步该尝试什么。
答案 0 :(得分:2)
您需要另一个序列号的连接条件。幸运的是,您可以使用row_number()
来获取此信息。这非常接近你想要的:
Select t1.row as row,
t2.name as p_name,
t2a.name as s_name
From table1 t1 left join
(select t2.*, row_number() over (partition by t2.id order by t2.id) as seqnum
from table2 t2
) t2
on t1.primary = t2.id left join
(select t2.*, row_number() over (partition by t2.id order by t2.id) as seqnum
from table2 t2
) t2a
on t1.secondary = t2a.id and t2.seqnum = t2a.seqnum;
不幸的是,它没有处理第二个列表比第一个列表长的情况。我认为这应该有效:
Select t1.row as row,
t2.name as p_name,
t2a.name as s_name
From table1 t1 left join
(select t2.*, row_number() over (partition by t2.id order by t2.id) as seqnum
from table2 t2
) t2
on t1.primary = t2.id full outer join
(select t2.*, row_number() over (partition by t2.id order by t2.id) as seqnum
from table2 t2
) t2a
on t1.secondary = t2a.id and t2.seqnum = t2a.seqnum;
答案 1 :(得分:1)
您可以使用rank()
功能在重复的名称中创建“订单”,然后将其用作加入条件的一部分:
SELECT t1.row,
primary_names.name AS p_name,
secondary_names.name AS s_name
FROM table1 t1
JOIN (SELECT id, name, RANK() OVER (PARTITION BY name ORDER BY id ASC) AS rk
FROM table2) primary_names
ON t1.primary = primary_names.id
LEFT JOIN (SELECT id, name, RANK() OVER (PARTITION BY name ORDER BY id ASC) AS rk
FROM table2) secondary_names
ON t1.secondary = secondary_names.id AND
primary_names.rk = secondary_names.rk
答案 2 :(得分:0)
您可能拥有错误的数据模型。您正在尝试在Table1和Table2之间建立关系。
如果要在Table1上为此关系添加外键约束,则数据库不允许您,因为FK必须始终指向引用表上的主键。如果您尝试在ID列上的Table2上添加PK,则数据库也不允许您,因为此列上的值不是唯一的。
查看您的数据模型。之后,您的代码应如下所示:
create table t2 (id number, name varchar2(10),
constraint t2PK primary key (id));
create table t1 (nrow number, prim number, sec number,
constraint fkPrim foreign key (prim) references t2(id),
constraint fkSec foreign key (sec) references t2(id));
insert into t2 values (1, 'Server1');
insert into t2 values (2, 'Server2');
insert into t2 values (3, 'Server3');
insert into t2 values (4, 'Server7');
insert into t2 values (5, 'Server8');
insert into t2 values (6, 'Server9');
insert into t1 values (1, 1, 2);
insert into t1 values (2, 3, 4);
insert into t1 values (3, 5, 6);
commit;
Select t1.nrow nrow,
t2a.name p_name,
t2b.name s_name
From t1
left join t2 t2a on t1.prim = t2a.id
left join t2 t2b on t1.sec = t2b.id;
NROW P_NAME S_NAME
---------- ---------- ----------
1 Server1 Server2
2 Server3 Server7
3 Server8 Server9