Разделение модели перечисления пути в MySQL
-
14-10-2019 - |
Вопрос
Я пытаюсь реализовать модель перечисления пути в соответствии с Джо Селко книга (стр. 38). Соответствующие атрибуты моей таблицы (и таблица поддержки, которые просто содержит последовательные целые числа) выглядят так:
Contribution
------------
ContributionID
PathString
_IntegerSeries
--------------
IntegerID
_Integerseries содержит целые числа от 1 до n, где N больше, чем мне когда -либо понадобится. Вклад содержит три записи:
1 1
2 12
3 123
... и я использую модифицированную версию запроса Джо:
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);
... Чтобы успешно вернуть набор результатов, содержащий все начальники взносов 3 в иерархии. Теперь, в этом примере, столбец PathString содержит простые целочисленные значения, и, очевидно, мы сталкиваемся с проблемами, как только мы достигли взноса.
1 1.
2 1.2.
3 1.2.3.
Теперь ... Книга не приводит примера получения начальства, когда PathString использует делимиторы ... так что мне придется выяснить это позже. Но это приводит пример для разделения пути PathString (что, я полагаю, поможет мне выполнить превосходные поиски). MySQL версия примера кода для этого такова:
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 || '.');
... но этот код возвращает пустой набор результатов. Я делаю что -то не так, но я не уверен, что. Подумал, что я поставлю это в сообщество Stackoverflow, прежде чем беспокоить Джо с электронным письмом. У кого -нибудь есть мысли?
ОБНОВИТЬ
Запрос Quassnoi ... немного немного изменился после тестирования, но точно так же, как и его оригинальный функциональный. Очень хорошо. Намного чище, чем то, что я использовал. Большое спасибо.
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;
Решение
Это потому что ||
в MySQL
это логический OR
, не строковая конкатенация.
Найти всех предков данного Contribution
, использовать:
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