将表连接到SQL Server中的两个一对多关系表

时间:2014-07-11 10:41:08

标签: sql sql-server sql-server-2008 sql-server-2005 reporting-services

周五快乐的人们,

我正在尝试编写一份SSRS报告,显示三个(实际上大约有12个,但只有三个相关)表的数据,这些表具有不正常的关系,并且数据背后的SQL查询很难实现。

涉及三个实体 - 采购订单,销售订单和交货。问题是采购订单可能有许多销售订单,还有许多与销售订单无关的交货......这太容易了。

销售订单和交货表都可以通过外键和每个中间表链接到采购订单表。

我需要基本上列出采购订单,销售订单清单和它们旁边的交货清单,对于任何无效的字段都使用NULL,以便在由SSRS读取时提供所需的输出人,即具有2个销售订单和4个交货日期的采购订单;

PO    SO      Delivery
1234  ABC     05/10
1234  DEF     09/10
1234  NULL    10/12
1234  NULL    14/12

以上(按PO分组)将告诉用户有两个销售订单和四个(未链接的)交货日期。

同样,如果有更多的SO而不是交付,我们在交付列中需要NULL;

PO    SO      Delivery
1234  ABC     03/08
1234  DEF     NULL
1234  GHI     NULL
1234  JKL     NULL  

以上是4个SO和一个交付日期的情况。

单独使用左外连接会产生太多重复 - 在这种情况下为8行,因为它为销售订单上的每个匹配提供了4个交付日期;

PO    SO      Delivery
1234  ABC     05/10
1234  ABC     09/10
1234  ABC     10/12
1234  ABC     14/12    
1234  DEF     05/10
1234  DEF     09/10
1234  DEF     10/12
1234  DEF     14/12

PO列很复杂,因为SSRS可以直观地对其进行分组 - 但是SO / Delivery字段不能被复制,因为这在报告中无法解决 - 如果我将列分组SOS的SSRS然后它仍然会为每一个提供4个交付日期。

我们的查询工作得很好的唯一情况是每个PO只有一个SO。在这种情况下,单个PO和SO号码一起复制用于x交付,并且可以在SSRS中整齐地分组。不幸的是,这是数据中罕见的情况。

我曾想过尝试使用某种窗口功能或CROSS APPLY,但两者都会掉线,因为它们会针对列出的每个PO编号重复,最终会吐出太多数据。

在考虑这个问题时,基于设置不足以在SQL中可行,我知道数据很糟糕。

任何帮助非常感谢。

EDIT - 表格模式的基本sqlfiddle链接。省略了许多不相关的列。 http://sqlfiddle.com/#!2/5ba16

示例数据......

Purchase Order
PO_Number Style
1001      Black work boots
1002      Green hat
1006      Red Scarf

Sales Order
Sales_order_number    PO_number    Qty   Retailer
A100-21               1001         15    Walmart
A100-22               1001         29    Walmart
A200-31               1006         1000  Asda

Delivery
Delivery_ID     Delivery_Date    PO_number
1543285         10/05/2014       1001
1543286         12/05/2014       1001
1543287         17/05/2014       1001
1543288         21/05/2014       1002

1 个答案:

答案 0 :(得分:1)

如果您为销售订单和交货中的元素分配行号,则可以链接该行号。

像这样的东西

declare @salesorders table (po int, so varchar(10))
declare @deliveries table (po int, delivery date)
declare @purchaseorders table (po int)
insert @purchaseorders values (123),(456)

insert @salesorders values (123,'a'),(123,'b'),(456,'c')
insert @deliveries values (123,'2014-1-1'),(456,'2014-2-1'),(456,'2014-2-1')


select *
from
(   
    select numbers.number, p.po, so.so, d.delivery from @purchaseorders p
    cross join (Select number from master..spt_values where type='p') numbers           
    left join (select *,ROW_NUMBER() over (partition by po order by so) sor  from @salesorders ) so
        on p.po = so.po and numbers.number = so.sor
    left join (select * , ROW_NUMBER() over (partition by po order by delivery) dor from @deliveries) d
        on p.po = d.po and numbers.number = d.dor
) v
where so is not null or delivery is not null
order by po,number