2016-05-09 2 views
1

В моей базе данных MYSQL используется древовидная система, в которой каждый элемент может иметь произвольное количество потомков. Каждый элемент имеет стандартный родительский столбец INT, содержащий его родительский элемент, а также столбец «VARCHAR» родителей, который состоит из строки, разделенной запятыми, содержащей все идентификаторы своего предка.Запрос MYSQL для подсчета потомков элементов путем нахождения его идентификатора в строке, разделенной запятой

id parent parents 
------------------------------- 
1  0   0 
2  1   0,1 
3  1   0,1 
4  3   0,1,3 

Мне нужно получить список всех предметов, каждый из которых подсчитан общим количеством потомков. Вот запрос, я до сих пор:

SELECT items.id AS item_id, 
COUNT(children.id) AS children 
FROM items items 
LEFT JOIN items children ON (items.id IN (children.parents)) 

Это просто отсылает обратно одну строку, с отсчетом ребенка 0. Как это сделать правильно?

EDIT:

После фиксации запроса так будет выглядеть так:

SELECT 
    i.id AS item_id, 
    COUNT(*) AS children 
FROM 
    items i 
LEFT JOIN 
    items c 
    ON (i.id IN (c.parents)) 
GROUP BY i.id; 

результаты показывают строки, но каждый из них имеет только один ребенок. Это не отражает данные, по-видимому, что-то не так с оператором IN (FIND_IN_SET делает то же самое).

EDIT2:

После изменения оператора IN к следующему

ON LOCATE(i.id, c.parents) > 0 

пункта 1 имеет правильное число детей (3), но остальные пункты все появляются как имеющие 1 ребенка. Элементы 2 и 4 должны иметь 0 и 3 должны иметь 1.

+1

во-первых, избегать использования одних и тех же псевдонимов несколько раз; «children» используется как псевдоним таблицы и псевдоним столбца; одинаково для псевдонимов «items» в «times»; эти псевдонимы делают запрос неоднозначным – Preuk

+0

, пожалуйста, опубликуйте свои операторы 'CREATE TABLE' и некоторые примеры данных – Preuk

+2

Это очень плохая схема, я бы изменил таблицу на использование [Nested Set Model] (https://en.wikipedia.org/ wiki/Nested_set_model) с прямым родительским столбцом в качестве резервной копии. Затем вы можете запускать очень простые запросы, чтобы получить подсчет потомков или любой другой счет, который вы хотите. – superphonic

ответ

1

Вам необходимо, чтобы GROUP BY items.id для COUNT() работал так, как планировалось.

С псевдонимами изменилось что-то менее неоднозначной:

SELECT 
    i.id AS item_id, 
    COUNT(*) AS children 
FROM 
    items i 
LEFT JOIN 
    items c 
    ON FIND_IN_SET(i.id, c.parents) > 0 
WHERE c.id <> i.id 
GROUP BY i.id; 

Для более сложных COUNT()/GROUP BY примеры см this question или MySQL documentation. Для FIND_IN_SET(), хороший пример here.

См sqlfiddle here

+0

Это немного лучше, но все еще не работает. Все строки отображаются с 1 ребенком. – IndigoFenix

+0

Ха-ха! Я думаю, что колонка родителей VARCHAR, разделенная запятой? Исправлен мой ответ для «find id in string» part – Preuk

+0

Ближе, но не совсем. Элемент верхнего уровня имеет правильное количество потомков, но все остальное по-прежнему имеет 1. – IndigoFenix