SQL JOIN 相乘结果集 - 笛卡尔积
SQL JOIN Multiplies Result Set - Cartesian Product
我有一个基地 table,我想再加入 2 个 table 以获得我需要的所有数据。在 运行 我的查询中,我得到了笛卡尔积,因为 table 中的 2 个(主要的 table 和我加入的另一个 table )被 non-unique
键。
这是一个例子:
发票 (i)
id order_id name comment
-----------------------------------------------------------------
1 500 Males Mice
2 500 Females Mice
3 500 Courier Fee Within City
订单 (o)
id order_number
------------------------------
500 AN5246516264
订单商品 (oi)
id order_id strain_id species_id comments
-----------------------------------------------------------------
1100 500 858 9876 Mice
1101 500 858 9876 Mice
1102 500 NULL NULL Within City
使用上面定义的 tables 这是我的查询:
查询
SELECT
i.name, i.comment,
o.order_number,
oi.strain_id, oi.species_id
FROM invoice i
LEFT JOIN order o
ON i.order_id = o.id
LEFT JOIN order_items oi
ON o.id = oi.order_id
在 运行 查询之后,我得到如下所示的笛卡尔积(不一定按顺序):
name comment order_number strain_id species_id
-----------------------------------------------------------------------
Males Mice AN5246516264 858 9876 ---> I want this row
Males Mice AN5246516264 858 9876
Males Within City AN5246516264 NULL NULL
Females Mice AN5246516264 858 9876
Females Mice AN5246516264 858 9876 ---> I want this row
Females Within City AN5246516264 NULL NULL
Courier Fee Mice AN5246516264 858 9876
Courier Fee Mice AN5246516264 858 9876
Courier Fee Within City AN5246516264 NULL NULL ---> I want this row
我明白这里发生了什么,我知道为什么会产生笛卡尔积,但我不知道如何解决我的问题。
我只想将 order_number
、strain_id
和 species_id
附加到 Invoice (i)
table。
是的,table 结构的构建方式有些奇怪。我确实相信数据库设计者在制作 table 时陶醉了,但这不是我现在可以改变的。
有什么建议吗?
编辑
我查看了所有 3 个 table,但找不到任何其他专栏来加入它们。我只剩下 order_id
.
您可以首先使用函数 row_number()
对表 i
和 oi
中的行进行编号,然后将其用作连接条件的一部分:
with i as (select row_number() over (partition by order_id order by id) rn, i.*
from invoice i),
oi as (select row_number() over (partition by order_id order by id) rn, oi.*
from order_items oi)
select i.name, i.comments, o.order_number, oi.strain_id, oi.species_id
from i left join orders o on i.order_id = o.id
left join oi on oi.order_id = o.id and oi.rn = i.rn
测试数据及输出:
create table invoice (id number(4), order_id number(4),
name varchar2(15), comments varchar2(20));
insert into invoice values (1, 500, 'Males', 'Mice');
insert into invoice values (2, 500, 'Females' ,'Mice');
insert into invoice values (3, 500, 'Courier Fee', 'Within City');
--
create table orders (id number(4), order_number varchar2(15));
insert into orders values (500, 'AN5246516264');
--
create table order_items(id number(5), order_id number(4),
strain_id number(5), species_id number(5), comments varchar2(20));
insert into order_items values(1100, 500, 858, 9876, 'Mice');
insert into order_items values(1101, 500, 858, 9876, 'Mice');
insert into order_items values(1102, 500, NULL, NULL, 'Within City');
输出:
NAME COMMENTS ORDER_NUMBER STRAIN_ID SPECIES_ID
--------------- -------------------- --------------- --------- ----------
Males Mice AN5246516264 858 9876
Females Mice AN5246516264 858 9876
Courier Fee Within City AN5246516264
我有一个基地 table,我想再加入 2 个 table 以获得我需要的所有数据。在 运行 我的查询中,我得到了笛卡尔积,因为 table 中的 2 个(主要的 table 和我加入的另一个 table )被 non-unique
键。
这是一个例子:
发票 (i)
id order_id name comment
-----------------------------------------------------------------
1 500 Males Mice
2 500 Females Mice
3 500 Courier Fee Within City
订单 (o)
id order_number
------------------------------
500 AN5246516264
订单商品 (oi)
id order_id strain_id species_id comments
-----------------------------------------------------------------
1100 500 858 9876 Mice
1101 500 858 9876 Mice
1102 500 NULL NULL Within City
使用上面定义的 tables 这是我的查询:
查询
SELECT
i.name, i.comment,
o.order_number,
oi.strain_id, oi.species_id
FROM invoice i
LEFT JOIN order o
ON i.order_id = o.id
LEFT JOIN order_items oi
ON o.id = oi.order_id
在 运行 查询之后,我得到如下所示的笛卡尔积(不一定按顺序):
name comment order_number strain_id species_id
-----------------------------------------------------------------------
Males Mice AN5246516264 858 9876 ---> I want this row
Males Mice AN5246516264 858 9876
Males Within City AN5246516264 NULL NULL
Females Mice AN5246516264 858 9876
Females Mice AN5246516264 858 9876 ---> I want this row
Females Within City AN5246516264 NULL NULL
Courier Fee Mice AN5246516264 858 9876
Courier Fee Mice AN5246516264 858 9876
Courier Fee Within City AN5246516264 NULL NULL ---> I want this row
我明白这里发生了什么,我知道为什么会产生笛卡尔积,但我不知道如何解决我的问题。
我只想将 order_number
、strain_id
和 species_id
附加到 Invoice (i)
table。
是的,table 结构的构建方式有些奇怪。我确实相信数据库设计者在制作 table 时陶醉了,但这不是我现在可以改变的。
有什么建议吗?
编辑
我查看了所有 3 个 table,但找不到任何其他专栏来加入它们。我只剩下 order_id
.
您可以首先使用函数 row_number()
对表 i
和 oi
中的行进行编号,然后将其用作连接条件的一部分:
with i as (select row_number() over (partition by order_id order by id) rn, i.*
from invoice i),
oi as (select row_number() over (partition by order_id order by id) rn, oi.*
from order_items oi)
select i.name, i.comments, o.order_number, oi.strain_id, oi.species_id
from i left join orders o on i.order_id = o.id
left join oi on oi.order_id = o.id and oi.rn = i.rn
测试数据及输出:
create table invoice (id number(4), order_id number(4),
name varchar2(15), comments varchar2(20));
insert into invoice values (1, 500, 'Males', 'Mice');
insert into invoice values (2, 500, 'Females' ,'Mice');
insert into invoice values (3, 500, 'Courier Fee', 'Within City');
--
create table orders (id number(4), order_number varchar2(15));
insert into orders values (500, 'AN5246516264');
--
create table order_items(id number(5), order_id number(4),
strain_id number(5), species_id number(5), comments varchar2(20));
insert into order_items values(1100, 500, 858, 9876, 'Mice');
insert into order_items values(1101, 500, 858, 9876, 'Mice');
insert into order_items values(1102, 500, NULL, NULL, 'Within City');
输出:
NAME COMMENTS ORDER_NUMBER STRAIN_ID SPECIES_ID
--------------- -------------------- --------------- --------- ----------
Males Mice AN5246516264 858 9876
Females Mice AN5246516264 858 9876
Courier Fee Within City AN5246516264