通过外键列获取多行

时间:2017-11-13 09:03:18

标签: sql-server join self-join

我有一个包含多个地址的地址表

Address: 
| Id   |   details   | ... |  
 - - - - - - - - -  - - - - - - - 
| 1    |  details |    ...        |
| 2    |  details |    ...        |
| 3    |  details |    ...        |
| 4    |  details |    ...        |

然后我有一个站点表,其中包含address.id作为FK来表示结算或送货地址,

Site: 
| Id   |   details   | Ship_Address_id  |  Bill_Address_id | ... |
 - - - - - - - - -  - - - - - - - 
| 1    |  details |          1           |        2          |     |
| 2    |  details |          1           |        3          |     |  
| 3    |  details |          4           |        4          |     |
| 4    |  details |          2           |        3          |     |

有没有办法连接这两个表,以便来自站点表的单行可以获取两行地址表,即使两列的地址相同。 我本来希望使用多个网站加入地址,但这不起作用:

这是我试过的:

SELECT CASE 
        WHEN ship.CRM_Address_Internal_Id_Ship IS NOT NULL THEN 'Ship'
        WHEN bill.CRM_Address_Internal_Id_Ship IS NOT NULL THEN 'Bill'
        ELSE '' END 
FROM Address as Adr
LEFT JOIN Site ship ON ship.Ship_Address_id = Adr.id 
LEFT JOIN Site bill ON bill.Bill_Address_id = Adr.id    

即使我不使用CASE,也不会针对网站为每个地址取两行。

请指教。

修改 这是所需的输出表: 在Site表中我们有两个不同的地址表ID(Ship / Bill),因此结果表应该为每个site.id显示两行。 例如,我为site.id 1和3提取记录

Result_Table:
| Address.ID | Address Details | TYPE | ... |
--------------------------------------------
| 1         | Other Details    | Ship | ... |
| 2         | Other Details    | Bill | ... |
| 4         | Other Details    | Ship | ... |
| 4         | Other Details    | Bill | ... |

2 个答案:

答案 0 :(得分:1)

有多种方法可以做到这一点。这是我通过 UNPIVOT 实现的示例,您可以看一下作为参考:

declare @address table(id int, details nvarchar(100))
declare @site table(id int, details nvarchar(100), ship_address_id int, bill_address_id int)

insert into @address values(1,'details 1')
insert into @address values(2,'details 2')
insert into @address values(3,'details 3')
insert into @address values(4,'details 4')

insert into @site values(1,'details 1',1,2)
insert into @site values(2,'details 1',1,3)
insert into @site values(3,'details 1',4,4)
insert into @site values(4,'details 1',2,5)


SELECT * 
FROM (
    SELECT s.id as site_id, s.bill_address_id, s.ship_address_id
    FROM @Site AS s
    INNER JOIN @Address AS sa ON s.Ship_Address_id = sa.Id
    INNER JOIN @Address AS ba ON s.Bill_Address_id = ba.Id
    WHERE s.id in (1,3)) p
UNPIVOT 
     (address_id FOR address_type IN 
      (Ship_Address_id, Bill_Address_id)
) AS unpvt

<强>输出

site_id     address_id  address_type
1           1           ship_address_id
1           2           bill_address_id
3           4           ship_address_id
3           4           bill_address_id

答案 1 :(得分:1)

看起来好像您正在寻找UNION ALL,而且您的桌子也在倒退。我认为你正在寻找更像这样的东西:

SELECT ship.id Site_id, CASE 
        WHEN ship.CRM_Address_Internal_Id_Ship IS NOT NULL THEN 'Ship'
        ELSE 'No Ship' END AddressPresent
FROM Site ship
LEFT JOIN Address Adr ON ship.Ship_Address_id = Adr.id

UNION ALL

SELECT bill.id Site_id, CASE 
        WHEN bill.CRM_Address_Internal_Id_Ship IS NOT NULL THEN 'Bill'
        ELSE 'No Bill' END AddressPresent
FROM Site bill
LEFT JOIN Address Adr ON bill.Bill_Address_id = Adr.id

我也想知道你是否有一个&#39; CRM_Address_Internal_Id_Bill&#39;应该在查询的第二部分的列?