如何在层次结构表关系中引用相同的ID

时间:2018-11-14 01:43:53

标签: sql-server

解决这个问题我已经坚持了好几天。我在SQL Server中有三个表:家庭表,资金表和桥接表Family_Funding。家庭表列出了每个家庭的所有家庭成员,例如:

家庭

id          name                                               Parent_id
----------- -------------------------------------------------- -----------
1           Father A                                           NULL
2           Son A                                              1
3           Daughter A                                         1
4           Father B                                           NULL
5           Mother B                                           NULL
6           Daughter B                                         4

“资助”表列出了每年的所有资助计划。还包括这些计划的举办年份。

资金

id          name                                               year
----------- -------------------------------------------------- ----------
1           Funding A                                          2010-01-14
2           Funding B                                          2011-11-14
3           Funding C                                          2014-01-01
4           Funding D                                          2016-01-01
5           Funding E                                          2018-01-01

最后一个是桥接表,其中列出了一个(只有一个)家庭成员收到的资金。

家庭资助

id          Family_id   Funding_id
----------- ----------- -----------
1           1           1
2           1           2
3           1           3
4           2           4
5           3           5

从上一张表中我们可以看到,直到2014年,家庭A通过父亲A获得资金,在2016年他们通过儿子A获得资金,在2018年通过女儿A获得资金。

如何实现此结果: 我想查看家庭A的最新资金,很遗憾,我只能得到结果 E资金,因为最新的一笔资金是通过女儿A获得的。但是由于女儿A是家庭A的成员, ,结果应包括通过儿子A和父亲A的其他资助。

预期结果

Family_name   Funding A   Funding B   Funding C   Funding D   Funding E
-----------   ---------   ---------   ---------   ---------   ---------
Daughter A    1           1           1           1           1

任何帮助将不胜感激!谢谢!

1 个答案:

答案 0 :(得分:0)

也许有一种更简洁的方法,但是它确实可以为您提供所需的东西。您应该看的主要部分是家庭的定义(A,B,C ...)。我使用的方法是:

LTRIM(RTRIM(RIGHT(fam.[Name],2)))

这是完整的代码。为了进行此练习,我将表数据放入表变量中。

DECLARE @Family TABLE (
    Id BIGINT NOT NULL PRIMARY KEY,
    [Name] VARCHAR(100) NOT NULL,
    ParentId BIGINT NULL
);

INSERT INTO @Family
(Id, [Name], ParentId)
VALUES
(1,'Father A',NULL),
(2,'Son A',1),
(3,'Daughter A',1),
(4,'Father B',NULL),
(5,'Mother B',NULL),
(6,'Daughter B',4);

DECLARE @Funding TABLE (
    Id BIGINT NOT NULL PRIMARY KEY,
    [Name] VARCHAR(100) NOT NULL,
    [Year] DATE NOT NULL
);

INSERT INTO @Funding
(Id, [Name], [Year])
VALUES
(1,'Funding A','2010-01-14'),
(2,'Funding B','2011-11-14'),
(3,'Funding C','2014-01-01'),
(4,'Funding D','2016-01-01'),
(5,'Funding E','2018-01-01');

DECLARE @FamilyFunding TABLE (
    Id BIGINT NOT NULL PRIMARY KEY,
    FamilyId BIGINT NOT NULL,
    FundingId BIGINT NOT NULL
);

INSERT INTO @FamilyFunding
(Id, FamilyId, FundingId)
VALUES
(1,1,1),
(2,1,2),
(3,1,3),
(4,2,4),
(5,3,5);

WITH CTE AS (
SELECT
    fam.[Name] AS FamilyName,
    fun.[Name] AS FundingName,
    fun.[Year],
    LTRIM(RTRIM(RIGHT(fam.[Name],2))) AS Family,
    ROW_NUMBER() OVER (PARTITION BY LTRIM(RTRIM(RIGHT(fam.[Name],2))) ORDER BY fun.[Year] DESC) AS RowNumber
FROM @FamilyFunding AS ff
INNER JOIN @Family AS fam
    ON ff.FamilyId = fam.Id
INNER JOIN @Funding AS fun
    ON ff.FundingId = fun.Id
),
FINAL AS (
SELECT
    a.Family,
    a.FamilyName AS MostRecentFamilyMember,
    a.[Year] AS MostRecentYear,
    b.FamilyName AS FamilyMember,
    b.FundingName,
    b.[Year],
    b.RowNumber
FROM CTE AS a
INNER JOIN CTE AS b
    ON a.Family = b.Family
WHERE a.RowNumber = 1
)

SELECT
    MostRecentFamilyMember,
    MAX([Funding A]) AS FundingA,
    MAX([Funding B]) AS FundingB,
    MAX([Funding C]) AS FundingC,
    MAX([Funding D]) AS FundingD,
    MAX([Funding E]) AS FundingE
FROM (
    SELECT
        f.Family,
        f.MostRecentFamilyMember,
        f.MostRecentYear,
        f.FamilyMember,
        f.FundingName,
        f.[Year],
        f.RowNumber,
        1 AS IsUsed
    FROM FINAL AS f
    ) AS b
PIVOT (
    MAX(IsUsed)
    FOR FundingName IN ([Funding A], [Funding B], [Funding C], [Funding D], [Funding E])
) AS p
GROUP BY
    MostRecentFamilyMember;