Domanda

Sto cercando di implementare un modello di enumerazione percorso secondo di Joe Celko libro (pagina 38). Gli attributi rilevanti della mia tavola (e la tabella di supporto che contiene solo numeri interi sequenziali) simile a questa:

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

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

_IntegerSeries contiene numeri interi da 1 a n, dove n è più grande di quanto avrete bisogno. Contributo contiene tre record:

1  1
2  12
3  123

... e io uso una versione modificata di interrogazione di 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);

... per tornare con successo un set di risultati contenente tutti i superiori di ContributionID 3 nella gerarchia. Ora, in questo esempio, la colonna PathString detiene valori pianura interi e, ovviamente, ci imbattiamo in problemi una volta che ci ha colpito ContributionID 10. Quindi modifichiamo la colonna PathString per includere i separatori:

1   1.
2   1.2.
3   1.2.3.

Ora ... il libro non dare un esempio di ottenere superiori quando gli usi PathString delimitatori ... quindi dovrò figura che più tardi fuori. Ma lo fa dare un esempio di come dividere un PathString (che sto cercando di indovinare che sta per aiutarmi a fare le ricerche superiori). La versione di MySQL del codice di esempio per fare questo è:

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 || '.');

... ma questo codice restituisce un set di risultati vuoto. Sto facendo qualcosa di sbagliato, ma io non sono sicuro di cosa. Ho pensato di mettere questo alla comunità StackOverflow prima di preoccuparsi di Joe con una e-mail. Qualcuno ha qualche idea?


UPDATE


interrogazione di Quassnoi ... leggermente modificata un po 'dopo il test, ma esattamente lo stesso come il suo originale punto di vista funzionale. Molto bella. Molto più pulito di quello che stavo usando. Un grande grazie.

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;
È stato utile?

Soluzione

This is because || in MySQL is boolean OR, not string concatenation.

To find all ancestors of a given Contribution, use:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top