SQL - 在字段之间创建关联(传递关系)

时间:2014-11-05 18:04:07

标签: sql sql-server oracle join group-by

我有一个sql表,其中包含实体A拥有实体B的附属关系列表,实体B拥有实体C等...我没有任何sql文本包含在这里因为我不确定从根本上在哪里开始。我认为多次加入表格不会产生预期的结果,因为它会排除某些“附属关系”。

我想要做的是将它们与那些相互关联的实体分配一些值(我不知道用于分组的值是什么)。以下示例可能最好地解释了这一点。

简化我的问题,我的表格中有以下两列。 (开头的数字是信息性的,只是代表记录编号,以便在下面提供我的描述。)

1 A | B
2 Z | B
3 Y | B
4 B | C
5 B | D
6 D | E
7 F | G

所以,A& B被视为“附属”。这也意味着因为“B”出现在记录#2,3,4和5中,所以Z,Y,C和D也与A& A相关联。 B,因此:

  

A,B,C,D,Y和Z都是附属的。

我还想更进一步,看看(RE:#5),因为B& D是附属的,(RE:#6)B和E也应该是附属的。因此,完整的联盟列表看起来像:

  

A,B,C,D, E ,Y和Z

自F& G只是出现在彼此的联系中,他们不会成为我刚才描述的更大的联盟的一部分。因此,我希望我的预期结果如下:

Entity | Grouping
A | Group1
B | Group1
C | Group1
D | Group1
E | Group1
Y | Group1
Z | Group1
F | Group2
G | Group2

我尽力解释这一点,所以我提前向任何遗漏细节或混淆/不完整的解释道歉。

提前感谢您的任何帮助!
最好,
罗比

1 个答案:

答案 0 :(得分:0)

我无法为ORACLE做任何事情,但你可以在sql server中使用递归CTE来管理它。继承我的样本解决方案,它就是你所要求的,假设你有一个表格,它将多个对多关系从一个表格映射到自己

DECLARE @testData table (EntityID int, EntityName varchar(1))
DECLARE @EntityRelations table (EntityID1 int, EntityID2 int)

INSERT INTO @testData
SELECT 1, 'A'
UNION
SELECT 2, 'B'
UNION
SELECT 3, 'C'
UNION
SELECT 4, 'D'
UNION
SELECT 5, 'E'
UNION
SELECT 6, 'F'
UNION
SELECT 7, 'G'
UNION
SELECT 8, 'Y'
UNION
SELECT 9, 'Z'

INSERT INTO @EntityRelations
SELECT 1, 2
UNION
SELECT 9, 2
UNION
SELECT 8, 2
UNION
SELECT 2, 3
UNION
SELECT 2, 4
UNION
SELECT 4, 5
UNION
SELECT 6, 7;


WITH Affiliations (EntityID, Entity1Name, Entity2Name) AS
(
    SELECT r.EntityID1
          ,e.EntityName as Entity1Name
          ,e2.EntityName as Entity2Name
    FROM @EntityRelations r
        JOIN @testData e ON e.EntityID = r.EntityID1
        JOIN @testData e2 ON e2.EntityID = r.EntityID2

    UNION ALL

    SELECT r.EntityID1
          ,e.EntityName as Entity1Name
          ,e2.EntityName as Entity2Name
    FROM @EntityRelations r
        JOIN @testData e ON e.EntityID = r.EntityID1
        JOIN @testData e2 ON e2.EntityID = r.EntityID2
        JOIN Affiliations a ON a.EntityID = r.EntityID2
)

,AffiliationsReverse (EntityID, Entity1Name, Entity2Name) AS
(
    SELECT r.EntityID2
          ,e.EntityName as Entity1Name
          ,e2.EntityName as Entity2Name
    FROM @EntityRelations r
        JOIN @testData e ON e.EntityID = r.EntityID1
        JOIN @testData e2 ON e2.EntityID = r.EntityID2

    UNION ALL

    SELECT r.EntityID2
          ,e.EntityName as Entity1Name
          ,e2.EntityName as Entity2Name
    FROM @EntityRelations r
        JOIN @testData e ON e.EntityID = r.EntityID1
        JOIN @testData e2 ON e2.EntityID = r.EntityID2
        JOIN AffiliationsReverse a ON a.EntityID = r.EntityID1
)


SELECT DISTINCT EntityName
FROM
(
SELECT a.Entity1Name AS EntityName
FROM Affiliations a
    JOIN AffiliationsReverse ar ON ar.EntityID = a.EntityID

UNION

SELECT a.Entity2Name AS EntityName
FROM Affiliations a
    JOIN AffiliationsReverse ar ON ar.EntityID = a.EntityID

UNION

SELECT ar.Entity1Name AS EntityName
FROM Affiliations a
    JOIN AffiliationsReverse ar ON ar.EntityID = a.EntityID

UNION

SELECT ar.Entity2Name AS EntityName
FROM Affiliations a
    JOIN AffiliationsReverse ar ON ar.EntityID = a.EntityID


) s