2010-05-10 4 views
0

je suis tombé sur le problème suivant pour créer dynamiquement des sujets de notre système ActiveMQ:Comment effectuer un traitement graphique non orienté à partir de données SQL

J'ai un certain nombre de processus (, ..., M_n), où n est pas grand, typiquement 5-10. Certains processus écouteront la sortie des autres, via une file d'attente de messages; ces bords sont spécifiés dans un fichier XML, par ex.

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

etc. Les bords sont rares, donc il n'y en aura pas beaucoup. Je vais analyser ce XML et stocker cette information dans une base de données SQL, une table pour les nœuds et une autre pour les bords.

Maintenant, je dois créer dynamiquement des chaînes de la forme

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 

où les balises sont générées de manière séquentielle. Quel est le meilleur moyen d'interroger SQL pour obtenir ces relations? Y a-t-il des outils ou d'autres tutoriels sur lesquels vous pouvez me diriger? Je n'ai jamais fait de graps avec SQL. Utiliser SQL est impératif, car nous l'utilisons aussi pour d'autres choses.

Merci!

+0

Etes-vous sûr de vouloir nommer les sujets de manière séquentielle - cela ne va-t-il pas être déroutant? Si les noms de sujet n'ont aucune signification, je les nommerais après le processus d'origine. Cela va aussi simplifier un peu votre requête. – mdma

+0

Non, ils peuvent être nommés de toutes les manières possibles. Bien sûr, ils doivent être uniques. – recipriversexclusion

Répondre

1

Ok, voici mon coup de couteau au problème.

Voici un croquis des noeuds et tables arêtes:

[nodes] 
node : varchar(xx) 

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

En supposant que votre db a un soutien pour CTEs, puis une requête structurée comme celui-ci rassemblera les relations et concaténer les résultats:

/* 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 

Je le fais d'emblée, donc sûrement quelques erreurs de syntaxe là-bas. J'espère que les commentaires expliquent l'intention.

+0

Merci beaucoup mdma! Je suis un novice en SQL, mais certains Googling ont montré que MySQL, qui est ce que nous utilisons, ne supporte pas CTE (http://stackoverflow.com/questions/1382573/how-do-you-use-the -with-clause-in-mysql). Cette technique est-elle facile à remplacer par d'autres approches supportées par MySQL? BTW, nous contrôlons MySQL en utilisant Hibernate. – recipriversexclusion

+0

Pitty vous n'avez pas mentionné ces détails au début. Vous pourriez probablement réécrire la plupart de ceci sans CTE, bien que je ne sois pas sûr comment vous feriez la concaténation récursive. Si vous utilisez hibernate, une meilleure approche consiste à lire les nœuds/bords dans hibernate et à coder une logique java pour produire les lignes de commande. – mdma

Questions connexes