GROUP_CONCAT с моделью вложенного набора - PullRequest
1 голос
/ 02 июня 2011

У меня есть приложение, которое использует класс модели вложенного набора для организации моих данных, однако я пытаюсь написать запрос, который будет group_concat мои результаты. Я знаю, что мне нужно где-то поместить некоторые операторы sub select, но я не могу понять это!

Вот моя структура на данный момент:

таблица: человек

 -----------+------------+-----------
|Person_ID  | Name       | Age       |
 -----------+------------+-----------
| 1         | Mark Vance | 19        |
| 2         | Michael Tsu| 22        |
| 3         | Mark Jones | 29        |
| 4         | Sara Young | 25        |
 -----------+------------+-----------

таблица: person_to_group

 ----+------------+-----------
|ID  | Person_ID  | Group_ID  |
 ----+------------+-----------
| 1  | 3          | 1         |
| 2  | 3          | 2         |
| 3  | 1          | 2         |
| 4  | 4          | 3         |
 ----+------------+-----------

таблица: группы

 ----------+--------------+--------------+-------------
|Group_ID  | Group_Name   | Group_Left   | Group_Right |
 ----------+--------------+--------------+-------------
| 1        | Root         | 1            | 6           |
| 2        | Node         | 2            | 5           |
| 3        | Sub Node     | 3            | 4           |
 ----------+--------------+--------------+-------------

Мне нужно сделать что-то подобное с моими результатами:

// Получаем идентификаторы group_ID для этого человека и помещаем их в тег класса ...

<li class="2 3">Sara Young is in the Sub Node Group</li>

Обратите внимание, что, хотя Сара находится в группе подузлов, ей все равно дается идентификатор для узла, поскольку она является дочерним узлом узла.

Ниже приведен запрос, с которым я работаю в качестве отправной точки.

SELECT *, GROUP_CONCAT( CAST( gg.Group_ID AS CHAR ) SEPARATOR ' ' ) Group_IDs
        FROM groups gg
        LEFT JOIN person_to_group AS t1 ON gg.Group_ID = t1.Group_ID
        LEFT JOIN person AS t2 ON t2.Person_ID = t1.Person_ID
        GROUP BY t2.per_ID 
        ORDER BY t2.Name ASC

Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

1 голос
/ 02 июня 2011

Вот как я бы написал запрос:

SELECT p.Name, 
  GROUP_CONCAT( g.Group_Name ) AS Group_List,
  GROUP_CONCAT( CAST( gg.Group_ID AS CHAR ) SEPARATOR ' ' ) AS Group_ID_List
FROM person AS p
INNER JOIN person_to_group AS pg ON p.Person_ID = pg.Person_ID
INNER JOIN groups AS g ON pg.Group_ID = g.Group_ID
INNER JOIN groups AS gg ON g.Group_Left BETWEEN gg.Group_Left AND gg.Group_Right
GROUP BY p.Name
ORDER BY p.Name ASC

Обратите внимание, что если вы группируете по имени, вам также необходимо GROUP_CONCAT список имен групп.Согласно вашей схеме, человек может принадлежать к нескольким группам из-за отношения «многие ко многим».

Я также рекомендую вообще не использовать SELECT *.Просто укажите нужные столбцы.

0 голосов
/ 02 июня 2011

Это было немного интересно, так как я занимаюсь программированием как на MsSQL, так и на MySql. В SQL я использовал функцию под названием STUFF. В MySQL вы можете использовать функцию INSERT. Я опробовал следующий запрос в MsSQL. У меня нет MySQL под рукой, чтобы попробовать мой запрос. Если у меня будет время, я опубликую версию запроса MySQL.

DECLARE @person TABLE (Person_ID INT, Name VARCHAR(50), Age INT)
INSERT INTO @person VALUES
(1,'Mark Vance',19),
(2,'Michael Tsu',22),
(3,'Mark Jones',29),
(4,'Sara Young',25)


DECLARE @groups TABLE (Group_ID INT, Group_Name VARCHAR(50), Group_Left INT, Group_Right INT)
INSERT INTO @groups VALUES
(1,'Root',1,6),
(2,'Node',2,5),
(3,'Sub Node',3,4)

DECLARE @person_to_group TABLE (ID INT, Person_ID INT, Group_ID INT)
INSERT INTO @person_to_group VALUES
(1,3,1),
(2,3,2),
(3,1,1),
(4,4,1),
(4,1,1)

SELECT *,STUFF((SELECT ',' + CAST(g.Group_ID AS VARCHAR) FROM @groups g 
    JOIN @person_to_group pg ON g.Group_ID = pg.Group_ID AND pg.Person_ID = a.Person_ID FOR XML PATH('')) , 1, 1, '' ) FROM @person a

Функция : INSERT (str, pos, len, newstr) Документация : http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_insert

...