将Mulitple表中的行合并到单个表

时间:2016-09-24 08:13:52

标签: sql-server-2012 database-administration

我有一个父表产品有多个子表 - 软管,Steeltubes,ElectricCables,FiberOptics。

ProductId - Product表中的主要关键字段 ProductId-软管,Steeltubes,ElectricCables,FiberOptics中的ForeignKey字段。

产品表与子表的关系为1对多

我想要结合所有表格的结果。 例如 - 产品P1具有PK字段ProductId,其在所有子表中用作FK。

如果Hoses表有4条记录,ProductId 50和Steeltubes表有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

2 个答案:

答案 0 :(得分:1)

假设子表之间没有关系,并且您只需要一个构成产品的所有子实体的列表,您可以生成一个cte,其行数等于所有子项中的最大条目数产品表。在下面的示例中,我使用了日期表来简化示例。 所以这个数据

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

创建一个笛卡尔连接(隐式连接帮助的稀有ocassions之一)pid到rn 结果

rn                   pid
-------------------- -----------
                   1           1
                   2           1
                   3           1
                   4           1
                   1           2
                   2           2
                   3           2
                   4           2

如果我们添加子表

;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

答案 1 :(得分:0)

事实上,预计8行的结果是结果,因为你的四个记录与另一个表中的第一个记录连接,然后你的四个记录与另一个表的第二个记录连接,它4 + 4 = 8。

事实上,您希望4条记录在结果中而不是8条,这表明您希望使用某种分组。您可以按ProductId对为SteelTubes发出的内部查询进行分组,但是您需要为其他列使用聚合函数。由于您只解释了所需输出的结构,而不是语义,我无法了解您当前对您的问题的了解,以确定您需要的聚合。

一旦找到第一个表的答案,您就可以轻松地将其他表添加到选择中,但是如果是大数据,您可能会遇到一些扩展问题,因此您可能希望存储这些组的表,在发生更改时进行维护并将其用于这些选择。