代码之家  ›  专栏  ›  技术社区  ›  recipriversexclusion

如何从SQL数据中执行无向图处理

  •  0
  • recipriversexclusion  · 技术社区  · 16 年前

    我在为ActiveMQ系统动态创建主题时遇到了以下问题:

    我有很多流程( M_1 M_n 在哪里 n 不是大的,通常是5-10。一些进程将通过消息队列监听其他进程的输出;这些边在XML文件中指定,例如。

    <link from="M1" to="M3"</link>
    <link from="M2" to="M4"</link>
    <link from="M3" to="M4"</link>
    

    等。边缘稀疏,所以不会有很多。我将解析此XML并将此信息存储在一个SQL数据库中,一个表用于节点,另一个表用于边缘。

    现在,我需要动态地创建表单的字符串

    M1.exe --output_topic=T1
    M2.exe --output_topic=T2
    M3.exe --input_topic=T1 --output_topic=T3
    M4.exe --input_topic=T2 --input_topic=T3 
    

    按顺序生成标记的位置。查询SQL以获取这些关系的最佳方法是什么?有什么工具或其他教程可以给我指点吗?我从来没有用SQL做过图形处理。

    使用SQL是必要的,因为我们也将它用于其他东西。

    谢谢!

    1 回复  |  直到 16 年前
        1
  •  1
  •   mdma    16 年前

    好吧,这是我解决问题的方法。

    以下是节点和边表的草图:

    [nodes]
    node : varchar(xx)
    
    [edges]
    outputNode : varchar(xx)
    inputNode : varchar(xx)
    

    假设您的数据库支持CTE,那么这样的查询结构将把关系组合在一起并连接结果:

    /* pair output nodes with a topic, assigned sequentially */
    WITH OutputTopics(node, topicNumber) AS (
       SELECT outputNode, ROW_NUMBER() (ORDER BY outputNode) AS topicNumber 
       FROM 
         (SELECT DISTINCT outputNode FROM edges) AS outputNodes
    ), 
    /* pair input nodes to the topic of associated output nodes */
    InputTopicNumbers(inputNode, topicNumber) AS (
       SELECT edges.inputNode, ot.topicNumber FROM edges INNER JOIN
           OutputTopics AS ot ON ot.node=edges.outputNode
    ),
    /* Recursive CTE to concat all topics together */
    InputTopics(inputNode, topics, topicNumber) AS (
          /* The seed for the recursion - all input nodes */
          SELECT inputNode, CAST ('' AS nvarchar(max)), 0 /* max topic handled for node */
          FROM InputTopicNumbers
          GROUP BY inputNode
       UNION ALL /* Add topics that are greater than those processed */
          /* recursively concat topic numbers in ascending order */
          SELECT i.inputNode, CONCAT(c.topics, ' --input-topic=T',i.topicNumber), i.topicNumber
          FROM InputTopics AS c 
          INNER JOIN InputTopicNumbers i ON i.inputNode=c.inputNode
          WHERE i.topicNumber > c.topicNumber
    ),
    /* Bring it all together - append each node with '.exe',
       list the output topic, if present
       Use the recursive CTE to concat all inputTopics */
    NodeCommands(node, exe, input, output) AS (
        SELECT nodes.node,
           CONCAT(nodes.node,'.exe'), 
           CONCAT(' --output_topic=T',ot.topicNumber), /* NULL if no output node */
           it.topics
        FROM nodes
        LEFT OUTER JOIN OutputTopics AS ot ON ot.node=nodes.node
        LEFT OUTER JOIN InputTopics AS it ON it.inputNode=nodes.node
    )
    /* finally our top-level query concatenates the parts to 
       arrive at a single command line */
    SELECT CONCAT(
       exe, 
       ISNULL(input, ''),
       ISNULL(output, '')) 
    FROM NodeCommands ORDER BY node
    

    我正在做这件事,所以肯定有一些语法错误。我希望这些评论能解释其意图。