【问题标题】:Combine rows from Mulitple tables into single table将多个表中的行合并到单个表中
【发布时间】:2016-09-24 08:13:52
【问题描述】:

我有一个带有多个子表的父表 Products -Hoses、Steeltubes、ElectricCables、FiberOptics。

ProductId - 产品表中的主键字段 ProductId- Hoses、Steeltubes、ElectricCables、FiberOptics 中的 ForeignKey 字段。

产品表与子表是一对多的关系

我想合并所有表格的结果。 例如 - 产品 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

【问题讨论】:

  • MySQL 标记被移除,因为它没有 CTE。

标签: sql-server-2012 database-administration


【解决方案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');

这件事

    ;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 to 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

【讨论】:

    【解决方案2】:

    实际上,8行的结果可以预期是结果,因为你的四条记录与另一张表中的第一条记录连接,然后你的四条记录与另一张表的第二条记录连接,使得它 4 + 4 = 8。

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

    找到第一个表的答案后,您也可以轻松地将其他表添加到选择中,但如果数据量很大,您可能会遇到一些缩放问题,因此您可能需要一个存储这些组的表,在发生变化时对其进行维护并将其用于这些选择。

    【讨论】:

      猜你喜欢
      • 2021-07-05
      • 1970-01-01
      • 2022-08-16
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 2013-12-14
      • 2019-06-27
      相关资源
      最近更新 更多