从点和关系形成三角形

时间:2010-05-18 15:09:33

标签: c# sql sql-server

我想从点生成三角形并在它们之间生成可选关系。并非所有的点都形成三角形,但很多都是三角形。

在初始结构中,我有一个包含以下表格的数据库:

节点(id,value)
关系(id,nodeA,nodeB,value)
三角形(id,relation1_id,relation2_id,relation3_id)

为了从节点和关系表生成三角形,我使用了以下查询:

INSERT INTO Triangles
SELECT t1.id, t2.id , t3.id, 
FROM Relations t1, Relations t2, Relations t3
WHERE t1.id < t2.id AND t3.id > t1.id AND
(
t1.nodeA = t2.nodeA 
AND (t3.nodeA = t1.nodeB AND t3.nodeB = t2.nodeB
OR t3.nodeA = t2.nodeB AND t3.nodeB = t1.nodeB)

OR 

t1.nodeA = t2.nodeB
AND (t3.nodeA = t1.nodeB AND t3.nodeB = t2.nodeA
OR t3.nodeA = t2.nodeA AND t3.nodeB = t1.nodeB)
)

它完美适用于小型数据。 (〜&lt; 50分) 然而,在某些情况下,我有大约100分,彼此相关,导致成千上万的关系。因此,当预期的三角形数量达到数十万甚至数百万时,查询可能需要几个小时。

我的主要问题不在于选择查询,而我看到它在Management Studio中执行,返回的结果很慢。我每分钟收到大约2000行,这对我来说是不可接受的。

事实上,操作的大小正在加强指数,这对性能造成了极大的影响。

我已经尝试过将其作为LINQ从我的代码中反对,但性能更差。

我也尝试在C#的读卡器上使用SqlBulkCopy来获得结果,也没有运气。

所以问题是......任何想法或解决方法?

2 个答案:

答案 0 :(得分:2)

我想你只需要这个:

INSERT
INTO    triangles (relation1_id, relation2_id, relation3_id)
SELECT  r12.id, r23.id, r13.id
FROM    relations r12
JOIN    relations r23
ON      r23.nodeA = r12.nodeB
JOIN    relations r13
ON      r13.nodeA = r12.nodeA
        AND r13.nodeB = r23.nodeB
ON      r12.nodeA = n1.id
WHERE   NOT EXISTS
        (
        SELECT  relation1_id, relation2_id, relation3_id
        FROM    triangles
        INTERSECT
        SELECT  r12.id, r23.id, r13.id
        )

进行以下检查约束:

ALTER TABLE relations ADD CONSTRAINT CHECK (nodeA < nodeB)

这一点是因为relations是对称的,你只需要每对存储一次关系,每个排列存储一次三角形。

检查约束确保按固定顺序每对存储一次关系。

设计查询使得三角形也以固定顺序存储:1 - 3首先,2 - 3秒,1 - 3,第三,其中1,2和3由关系链接的节点的顺序确定。

另请注意,三角形的数量增长为O(n^3),而非指数式增长(O(exp(N)))。

对于100个节点,最多可以有100 * 99 * 98 / 6 = 161700个三角形。

答案 1 :(得分:1)

您使用的查询存在一些问题:

  1. “t1.id&lt; t2.id AND t3.id&gt; t1.id”不会阻止t2 = t3。将其更改为“WHERE t1.id&lt; t2.id AND t3.id&gt; t2.id”
  2. t1.nodeA可能根本不存在于t2中。
  3. Quassnoi的解决方案看起来很有希望。它也有问题。首先,它是将节点ID而不是关系ID选择为三角形。其次,不检查n1和n3之间的关系是否存在。我将声明重写为:

    INSERT
    INTO    triangles (relation1_id, relation2_id, relation3_id)
    SELECT  r12.id, r23.id, r13.id
    FROM    relations r12
    JOIN    relations r23
    ON      r12.nodeB = r23.nodeA
    JOIN    relations r13
    ON      r12.nodeA = r13.nodeA AND r23.nodeB = r13.nodeB
    WHERE   NOT EXISTS
            (
            SELECT  relation1_id, relation2_id, relation3_id
            FROM    triangles
            WHERE   relation1_id = r12.id AND relation2_id = r23.id AND relation3_id = r13.id
            )
    

    此解决方案不依赖于关系表中ID排序的任何约束,也不保证三角形表中任何ID顺序。

相关问题