Pregunta

Estoy tratando de implementar un modelo de enumeración Path según libro de Joe Celko (página 38). Los atributos relevantes de mi mesa (y la mesa de soporte que solo contiene números enteros consecutivos) tener este aspecto:

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

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

_IntegerSeries contiene números enteros de 1 a n, donde n es mayor de lo que necesitará siempre. Contribución contiene tres registros:

1  1
2  12
3  123

... y yo utilizo una versión modificada de la pregunta 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);

... para regresar con éxito un conjunto de resultados que contiene todos los superiores de ContributionID 3 en la jerarquía. Ahora, en este ejemplo, la columna de la PathString contiene valores enteros sin formato y, obviamente, nos encontramos con problemas una vez que golpeamos ContributionID 10. Así modificamos la columna de la PathString para incluir separadores:

1   1.
2   1.2.
3   1.2.3.

Ahora ... el libro no dar un ejemplo de conseguir superiores cuando los delimitadores de los usos PathString ... así que tendrán que darse cuenta de eso después. Pero nos da un ejemplo de cómo dividir un PathString (que supongo que va a ayudarme a hacer búsquedas superiores). La versión de MySQL del código de ejemplo para hacer esto es:

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

... pero este código devuelve un conjunto de resultados vacío. Estoy haciendo algo mal, pero no estoy seguro de qué. Pensé que podría poner esto a la comunidad stackoverflow antes de molestar a Joe con un correo electrónico. Alguien tiene alguna idea?


Actualizar


consulta de Quassnoi ... modificó ligeramente un poco después de las pruebas, pero exactamente igual que su original, funcionalmente. Muy agradable. Mucho más limpio que lo que yo estaba usando. Muchas gracias.

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;
¿Fue útil?

Solución

Esto se debe a || en MySQL es OR booleano, no concatenación de cadenas.

Para encontrar todos los ancestros de un Contribution dada, utilice:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top