Question

Je suis en train de mettre en œuvre un modèle de chemin Enumeration selon Joe Celko livre (page 38). Les attributs pertinents de ma table (et la table de support qui ne contient que des entiers séquentiels) ressembler à ceci:

Contribution
------------
ContributionID
PathString

_IntegerSeries
--------------
IntegerID

_IntegerSeries contient des entiers de 1 à n où n est plus grand que je ne vais jamais besoin. Contribution contient trois dossiers:

1  1
2  12
3  123

... et j'utilise une version modifiée de la requête de Joe:

SELECT SUBSTRING( c1.PathString
     FROM (s1.IntegerID * CHAR_LENGTH(c1.ContributionID))
     FOR CHAR_LENGTH(c1.ContributionID)) AS ContID
FROM
 Contribution c1, _IntegerSeries s1
WHERE
 c1.ContributionID = 3
 AND s1.IntegerID <= CHAR_LENGTH(c1.PathString)/CHAR_LENGTH(c1.ContributionID);

... pour revenir avec succès un jeu de résultats contenant tous les supérieurs de ContributionID 3 dans la hiérarchie. Maintenant, dans cet exemple, la colonne PathString détient des valeurs entières simple et évidemment nous courons en difficulté une fois que nous avons touché ContributionID 10. Nous modifions la colonne PathString pour inclure les séparateurs:

1   1.
2   1.2.
3   1.2.3.

... le livre ne donne pas un exemple d'obtenir des supérieurs lorsque les PathString ... donc délimiteurs utilisations que je vais devoir comprendre cela plus tard. Mais il ne donne un exemple sur la façon de diviser un PathString (que je devine va me aider faire des recherches supérieures). La version MySQL du code exemple pour ce faire est:

SELECT SUBSTRING( '.' || c1.PathString || '.'
     FROM s1.IntegerID + 1
     FOR LOCATE('.', '.' || c1.PathString || '.', s1.IntegerID + 1) - s1.IntegerID - 1) AS Node
FROM _IntegerSeries s1, Contribution c1
WHERE
 SUBSTRING('.' || c1.PathString || '.' FROM s1.IntegerID FOR 1) = '.'
 AND IntegerID < CHAR_LENGTH('.' || c1.PathString || '.');

... mais ce code renvoie un jeu de résultats vide. Je fais quelque chose de mal, mais je ne sais pas quoi. Je mettrais Figured ceci à la communauté stackoverflow avant Joe prendre la peine avec un e-mail. Quelqu'un at-il des pensées?


UPDATE


La requête de Quassnoi ... légèrement modifié un peu après le test, mais exactement le même que son origine fonctionnelle. Très agréable. Beaucoup plus propre que ce que j'utilisais. Un grand merci.

SET @contributionID = 3;

SELECT  ca.*
FROM
    Contribution c INNER JOIN _IntegerSeries s
        ON s.IntegerID < @contributionID AND SUBSTRING_INDEX(c.PathString, '.', s.IntegerID) <> SUBSTRING_INDEX(c.PathString, '.', s.IntegerID + 1)
    INNER JOIN Contribution ca
        ON ca.PathString = CONCAT(SUBSTRING_INDEX(c.PathString, '.', s.IntegerID), '.')
WHERE c.ContributionID = @contributionID;
Était-ce utile?

La solution

En effet, dans || MySQL est OR booléen, pas concaténation de chaînes.

Pour tous les ancêtres d'un Contribution donné, utilisez:

SELECT  ca.*
FROM    Contribution с
JOIN    IntegerSeries s
ON      IntegerID < CHAR_LENGTH(c.path)
        AND SUBSTRING_INDEX(c.path, '.', IntegerID) <> SUBSTRING_INDEX(c.path, '.', IntegerID + 1)
JOIN    Contribution ca
ON      ca.path = CONCAT(SUBSTRING_INDEX(c.path, '.', IntegerID), '.')
WHERE   c.ContributionID = 3
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top