T-SQL复杂自我加入

时间:2016-08-18 07:24:12

标签: sql sql-server sql-server-2008 tsql join

方案

我有一个场景涉及通过另一个复杂的自联接来返回正确的结果。我要做的是创建一个Ms SQL Server(2008)视图来呈现数据。

这种情况涉及持有产品库存的连锁企业内的个别公司,然后可以选择与其所属链中的其他公司共享该股票。规则如下:

  • 如果公司持有产品库存并且他们正在共享该库存,那么他们可用的数量就是他们的库存以及来自其链中公司的任何共享库存
  • 如果一家公司持有某种产品的库存但是他们没有共享这种库存,那么他们可以获得的数量只是他们的库存
  • 如果公司没有持有股票,那么他们只拥有其链中其他公司可以分享其股票的数量

表格

Create Table dbo.Chain(
    ChainId int Identity(1,1) Not Null PRIMARY KEY,
    Name nvarchar(255) Not Null)
Go
Insert into Chain(Name)Values('Technology Brothers')
Insert into Chain(Name)Values('Kings Of Tech')
Go

Create Table dbo.Company(
    CompanyId int Identity(1,1) Not Null PRIMARY KEY,
    Name nvarchar(255) Not Null,
    ChainId int Not Null)
Go
Insert into Company(Name, ChainId)Values('Techies', 1)
Insert into Company(Name, ChainId)Values('MotherboardsRUs', 1)
Insert into Company(Name, ChainId)Values('RAM Bros', 1)
Insert into Company(Name, ChainId)Values('Silicon Station', 2)
Insert into Company(Name, ChainId)Values('Nerd Place', 2)
Go

Create Table dbo.Product(
    ProductId int Identity(1,1) Not Null PRIMARY KEY,
    Name nvarchar(255) Not Null)
Go
Insert into Product(Name)Values('Laser Mouse')
Insert into Product(Name)Values('MBoard 101')
Insert into Product(Name)Values('CAT Cable')
Insert into Product(Name)Values('Big Screen')
Insert into Product(Name)Values('J Speakers')
Insert into Product(Name)Values('Blue USB')

Create Table CompanyProduct(
    CompanyProductId int Identity(1,1) Not Null PRIMARY KEY,
    CompanyId int,
    ProductId int,
    Quantity int,
    IsShared bit)
Go
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(1, 1, 10, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(1, 2, 1, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(1, 3, 5, 0)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(1, 4, 2, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(2, 1, 5, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(2, 2, 10, 0)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(3, 3, 1, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(3, 4, 4, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(3, 5, 10, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(4, 1, 5, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(4, 3, 10, 0)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(5, 2, 2, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(5, 4, 10, 1)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(5, 5, 3, 0)
Insert into CompanyProduct(CompanyId, ProductId, Quantity, IsShared)Values(5, 6, 8, 0)
Go

预期结果

对于每个可用数量的产品,每个公司的结果应该包含一行。换句话说,如果他们没有任何股票而且他们的链中没有人共享任何股票,那么该产品将没有任何行。否则,将会有一行包含他们拥有的数量,与他们共享的数量以及他们可用的总数量。

下表概述了上面插入数据的结果。

CompanyId   ChainId     ProductId   IsShared    My Quantity    Shared Quantity   Total Quantity
1           1           1           1           10             5                 15
1           1           2           1           1              0                 1
1           1           3           0           5              NULL              5
1           1           4           1           2              4                 6
1           1           5           NULL        0              10                10
2           1           1           1           10             5                 15
2           1           2           0           10             NULL              10
2           1           3           NULL        0              1                 1
2           1           4           NULL        0              6                 6
2           1           5           NULL        0              10                10
3           1           1           NULL        0              15                15
3           1           2           NULL        0              1                 1
3           1           3           1           1              0                 1
3           1           4           1           4              2                 6
3           1           5           1           10             0                 10
4           2           1           1           5              0                 5
4           2           2           1           0              2                 2
4           2           3           0           10             NULL              10
4           2           4           NULL        0              10                10
5           2           1           NULL        0              5                 5
5           2           2           1           2              0                 2
5           2           4           1           10             0                 10
5           2           5           0           3              NULL              3
5           2           6           0           8              NULL              8

1 个答案:

答案 0 :(得分:0)

它有点乱,但我认为您可以使用它来获取所需的数据。

SELECT com.name, pro.name, ISNULL(cop.Quantity, 0) [Own Stock], ISNULL(cop.Quantity, 0) + SUM(ISNULL(copsha.Quantity, 0)) [Shared Stock]
FROM Company com
JOIN Chain cha ON cha.ChainId = com.ChainId
LEFT JOIN Product pro ON pro.ProductId = pro.ProductId
LEFT JOIN CompanyProduct cop ON cop.CompanyId = com.CompanyId   
                    AND pro.ProductId = cop.ProductId
JOIN Company comsha ON comsha.CompanyId <> com.CompanyId
                AND comsha.ChainId = com.ChainId
LEFT JOIN CompanyProduct copsha ON (copsha.CompanyId = comsha.CompanyId
                            AND copsha.ProductId = pro.ProductId)
WHERE copsha.IsShared = 1
GROUP BY com.name, pro.name, cop.ProductId, cop.Quantity
HAVING ISNULL(cop.Quantity, 0) > 0
OR SUM(ISNULL(copsha.Quantity, 0)) > 0