将多个 table 中的行合并为单个 table
Combine rows from Mulitple tables into single table
我有一个 parent table 产品有多个 child tables -软管、钢管、电力电缆、光纤。
ProductId - 产品中的主键字段 table
ProductId- 软管、钢管、电缆、光纤中的 ForeignKey 字段。
产品 table 与 Child tables
具有一对多关系
我想合并所有 tables 的结果。
例如 - 产品 P1 具有 PK 字段 ProductId,它在所有 child table 中用作 FK。
如果 Hoses table 有 4 条 ProductId 为 50 的记录,Steeltubes table 有 2 条 ProductId 为 50 的记录,当我执行左连接时,左连接正在做记录的笛卡尔积,结果显示 8 条记录但是应该是4条记录。
;with HOSESTEELCTE
as
(
select '' as ModeType, '' as FiberOpticQty , '' as NumberFibers, '' as FiberLength, '' as CableType , '' as Conductorsize , '' as Voltage,'' as ElecticCableLength , s.TubeMaterial , s.TubeQty, s.TubeID , s.WallThickness , s.DWP ,s.Length as SteelLength , h.HoseSeries, h.HoseLength ,h.ProductId
from Hoses h
left join
(
--'' as HoseSeries,'' as HoseLength ,
select TubeMaterial , TubeQty, TubeID , WallThickness , DWP , Length,ProductId from SteelTubes
) s on (s.ProductId = h.ProductId)
) select * from HOSESTEELCTE
事实上,8行的结果应该是结果,因为你的四条记录在另一个table中与第一条记录连接,然后你的四条记录与第二条记录连接另一个 table,使它成为 4 + 4 = 8。
您希望结果中有 4 条记录而不是 8 条记录这一事实表明您想要使用某种分组。您可以按 ProductId 对为 SteelTubes 发出的内部查询进行分组,但随后您将需要对其他列使用聚合函数。由于您只解释了所需输出的结构,而不是语义,因此我无法根据我目前对您的问题的了解来确定您需要什么聚合。
找到第一个 table 的答案后,您将能够轻松地将其他 table 也添加到选择中,但如果数据量很大,您可能会得到一些缩放问题,因此您可能希望有一个 table 来存储这些组,在发生变化时维护它并将其用于这些选择。
假设 child table 之间没有任何关系,您只需要一个包含构成产品的所有 child 实体的列表,您可以生成一个包含数字的 cte等于产品所有 child table 中最大条目数的行数。在下面的示例中,我使用日期 table 来简化示例。
所以对于这个数据
create table products(pid int);
insert into products values
(1),(2);
create table hoses (pid int,descr varchar(2));
insert into hoses values (1,'h1'),(1,'h2'),(1,'h3'),(1,'h4');
create table steeltubes (pid int,descr varchar(2));
insert into steeltubes values (1,'t1'),(1,'t2');
create table electriccables(pid int,descr varchar(2));
truncate table electriccables
insert into electriccables values (1,'e1'),(1,'e2'),(1,'e3'),(2,'e1');
这个cte
;with cte as
(select row_number() over(partition by p.pid order by datekey) rn, p.pid
from dimdate, products p
where datekey < 20050105)
select * from cte
创建笛卡尔连接(隐式连接有帮助的罕见情况之一)pid 到 rn
结果
rn pid
-------------------- -----------
1 1
2 1
3 1
4 1
1 2
2 2
3 2
4 2
如果我们添加 child tables
;with cte as
(select row_number() over(partition by p.pid order by datekey) rn, p.pid
from dimdate, products p
where datekey < 20050106)
select c.pid,h.descr hoses,s.descr steeltubes,e.descr electriccables from cte c
left join (select h.*, row_number() over(order by h.pid) rn from hoses h) h on h.rn = c.rn and h.pid = c.pid
left join (select s.*, row_number() over(order by s.pid) rn from steeltubes s) s on s.rn = c.rn and s.pid = c.pid
left join (select e.*, row_number() over(order by e.pid) rn from electriccables e) e on e.rn = c.rn and e.pid = c.pid
where h.rn is not null or s.rn is not null or e.rn is not null
order by c.pid,c.rn
我们明白了
pid hoses steeltubes electriccables
----------- ----- ---------- --------------
1 h1 t1 e1
1 h2 t2 e2
1 h3 NULL e3
1 h4 NULL NULL
2 NULL NULL e1
我有一个 parent table 产品有多个 child tables -软管、钢管、电力电缆、光纤。
ProductId - 产品中的主键字段 table ProductId- 软管、钢管、电缆、光纤中的 ForeignKey 字段。
产品 table 与 Child tables
具有一对多关系我想合并所有 tables 的结果。 例如 - 产品 P1 具有 PK 字段 ProductId,它在所有 child table 中用作 FK。
如果 Hoses table 有 4 条 ProductId 为 50 的记录,Steeltubes table 有 2 条 ProductId 为 50 的记录,当我执行左连接时,左连接正在做记录的笛卡尔积,结果显示 8 条记录但是应该是4条记录。
;with HOSESTEELCTE
as
(
select '' as ModeType, '' as FiberOpticQty , '' as NumberFibers, '' as FiberLength, '' as CableType , '' as Conductorsize , '' as Voltage,'' as ElecticCableLength , s.TubeMaterial , s.TubeQty, s.TubeID , s.WallThickness , s.DWP ,s.Length as SteelLength , h.HoseSeries, h.HoseLength ,h.ProductId
from Hoses h
left join
(
--'' as HoseSeries,'' as HoseLength ,
select TubeMaterial , TubeQty, TubeID , WallThickness , DWP , Length,ProductId from SteelTubes
) s on (s.ProductId = h.ProductId)
) select * from HOSESTEELCTE
事实上,8行的结果应该是结果,因为你的四条记录在另一个table中与第一条记录连接,然后你的四条记录与第二条记录连接另一个 table,使它成为 4 + 4 = 8。
您希望结果中有 4 条记录而不是 8 条记录这一事实表明您想要使用某种分组。您可以按 ProductId 对为 SteelTubes 发出的内部查询进行分组,但随后您将需要对其他列使用聚合函数。由于您只解释了所需输出的结构,而不是语义,因此我无法根据我目前对您的问题的了解来确定您需要什么聚合。
找到第一个 table 的答案后,您将能够轻松地将其他 table 也添加到选择中,但如果数据量很大,您可能会得到一些缩放问题,因此您可能希望有一个 table 来存储这些组,在发生变化时维护它并将其用于这些选择。
假设 child table 之间没有任何关系,您只需要一个包含构成产品的所有 child 实体的列表,您可以生成一个包含数字的 cte等于产品所有 child table 中最大条目数的行数。在下面的示例中,我使用日期 table 来简化示例。 所以对于这个数据
create table products(pid int);
insert into products values
(1),(2);
create table hoses (pid int,descr varchar(2));
insert into hoses values (1,'h1'),(1,'h2'),(1,'h3'),(1,'h4');
create table steeltubes (pid int,descr varchar(2));
insert into steeltubes values (1,'t1'),(1,'t2');
create table electriccables(pid int,descr varchar(2));
truncate table electriccables
insert into electriccables values (1,'e1'),(1,'e2'),(1,'e3'),(2,'e1');
这个cte
;with cte as
(select row_number() over(partition by p.pid order by datekey) rn, p.pid
from dimdate, products p
where datekey < 20050105)
select * from cte
创建笛卡尔连接(隐式连接有帮助的罕见情况之一)pid 到 rn 结果
rn pid
-------------------- -----------
1 1
2 1
3 1
4 1
1 2
2 2
3 2
4 2
如果我们添加 child tables
;with cte as
(select row_number() over(partition by p.pid order by datekey) rn, p.pid
from dimdate, products p
where datekey < 20050106)
select c.pid,h.descr hoses,s.descr steeltubes,e.descr electriccables from cte c
left join (select h.*, row_number() over(order by h.pid) rn from hoses h) h on h.rn = c.rn and h.pid = c.pid
left join (select s.*, row_number() over(order by s.pid) rn from steeltubes s) s on s.rn = c.rn and s.pid = c.pid
left join (select e.*, row_number() over(order by e.pid) rn from electriccables e) e on e.rn = c.rn and e.pid = c.pid
where h.rn is not null or s.rn is not null or e.rn is not null
order by c.pid,c.rn
我们明白了
pid hoses steeltubes electriccables
----------- ----- ---------- --------------
1 h1 t1 e1
1 h2 t2 e2
1 h3 NULL e3
1 h4 NULL NULL
2 NULL NULL e1