在家庭关系上添加家庭 ID 列 Table

add Family ID Column on Family Relations Table

我的源数据库中有一个 table 将一个人与其妻子/丈夫以及他们的 child 人(如果有的话)联系起来。

与child人的关系可以通过妻子或丈夫,但其中一个成年人与child人只有一个关系,而与child人之间只有一个关系丈夫和妻子。与配偶有关系的成年人不一定是与 child/children.

有关系的成年人

我想创建一个输出,其中包含每个人及其家庭的唯一 ID。但我似乎无法理解如何获得结果。

下面是我的源数据示例。

+--------+------+
| FromID | ToID |
+--------+------+
|      1 |    2 |
|      2 |    3 |
|      2 |    4 |
|      5 |    6 |
|      6 |    7 |
|      8 |    9 |
+--------+------+

   CREATE TABLE [dbo].[Relations](
            [FromID] [int] NULL,
            [ToID] [int] NULL
        ) 
        INSERT [dbo].[Relations] ([FromID], [ToID]) VALUES (1, 2)
        INSERT [dbo].[Relations] ([FromID], [ToID]) VALUES (2, 3)
        INSERT [dbo].[Relations] ([FromID], [ToID]) VALUES (2, 4)
        INSERT [dbo].[Relations] ([FromID], [ToID]) VALUES (5, 6)
        INSERT [dbo].[Relations] ([FromID], [ToID]) VALUES (6, 7)
        INSERT [dbo].[Relations] ([FromID], [ToID]) VALUES (8, 9)

在此示例数据中:

下面是想要的结果:

+----------+----------+
| PersonID | FamilyID |
+----------+----------+
|        1 |        1 |
|        2 |        1 |
|        3 |        1 |
|        4 |        1 |
|        5 |        2 |
|        6 |        2 |
|        7 |        2 |
|        8 |        3 |
|        9 |        3 |
+----------+----------+

首先你需要找出每个家庭的丈夫并分配ID。您查找未显示为 [FromID]

的 ID

SQL DEMO

WITH husband as (      
    SELECT R1.[FromID] as [ID],
           ROW_NUMBER() OVER (ORDER BY R1.[FromID]) as rn
    FROM [Relations] R1
    LEFT JOIN [Relations] R2
      ON R1.[FromID] = R2.[ToID]
    WHERE R2.[FromID] IS NULL
)
SELECT *
FROM husband

输出

然后只需使用递归查询来获取该 [ID]

的所有家庭成员

https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx

编辑:

因为你的树只有两层深度,你可以使用 JOINS 来做到这一点,但如果你想处理单亲家庭,我可以看到问题。

SQL DEMO

WITH husbands as (      
    SELECT  ROW_NUMBER() OVER (ORDER BY R1.[FromID]) as [familyID],
            R1.[FromID] as [ID]           
    FROM [Relations] R1
    LEFT JOIN [Relations] R2
      ON R1.[FromID] = R2.[ToID]
    WHERE R2.[FromID] IS NULL
), wifes as (
    SELECT H.[familyID], R1.[ToID] as [ID]
    FROM husbands H
    JOIN Relations R1
      ON H.[ID] = R1.[FromID] 
), childrens as (
    SELECT H.[familyID], R2.[ToID] as [ID]
    FROM husbands H
    JOIN Relations R1
      ON H.[ID] = R1.[FromID] 
    JOIN Relations R2
      ON R1.[ToID] = R2.[FromID]     
)    
SELECT * FROM husbands UNION 
SELECT * FROM wifes UNION 
SELECT * FROM childrens

输出

这是另一种实现此结果的方法:

SELECT DISTINCT
  COALESCE(h.husband, d.dependents) AS id,
  COALESCE(d.familyid, h.familyid) AS familyid
FROM (SELECT
            r.ToID AS dependents,
            DENSE_RANK() OVER (ORDER BY COALESCE(r2.Fromid, r.Fromid)) AS familyid
      FROM Relations r
      LEFT JOIN Relations r2
        ON r.[FromID] = r2.ToID) d
FULL JOIN (SELECT
              COALESCE(r2.Fromid, r.Fromid) AS husband,
              DENSE_RANK() OVER (ORDER BY COALESCE(r2.Fromid, r.Fromid)) AS familyid
           FROM Relations r
           LEFT JOIN Relations r2
             ON r.[FromID] = r2.ToID) h
  ON d.dependents = h.husband