2013-08-20 3 views
1

У меня есть три таблицы. TB_Main - это таблица сущностей. TB_BoardMembers - таблица людей. TB_BoardMembersLINK - это таблица мостов, которая ссылается на два других идентификаторами, а также имеет даты начала и окончания, когда Person находился на борту Entity. Эти даты часто являются неполными.Использование GROUP_CONCAT

Мне было предложено экспортировать как часть отчета CSV с одной строкой на каждый объект в год, в котором у меня есть список членов совета за тот год с их занятиями в одном поле, ограниченном символами новой строки.

Мне не нужен bml.Entity в результате, но добавил его, чтобы попытаться отладить. Я получаю одну строку, где ожидаю 85. Пробовал с GROUP BY и без нее, и тот факт, что результат тот же, говорит о том, что я злоупотребляю GROUP_CONCAT. Как я должен построить это, чтобы получить желаемый результат?

SELECT 
GROUP_CONCAT(
DISTINCT CONCAT(bm.First, ' ', bm.Last, 
IF (bm.Occupation != '', ' - ', ''), 
bm.Occupation) SEPARATOR "\n") as Board, 
bml.Entity 
FROM 
TB_Main arfe, 
TB_BoardMembers bm, 
TB_BoardMembersLINK bml 
WHERE YEAR(bml.start) <= 2011 
AND (YEAR(bml.end) >= 2011 OR bml.end IS NULL) 
AND bml.start > 0 
AND bml.Entity = arfe.ID 
GROUP BY bml.Entity 
ORDER BY Board 
+2

ИМХО проблема не с 'GROUP_CONCAT', а с ненадлежащим JOIN и. – peterm

ответ

2

Есть несколько вопросов с этим запросом. Основная проблема заключается в том, что вам не хватает условия для соединения членов совета с таблицей ссылок, поэтому у вас есть кросс-соединение, то есть вы будете возвращать каждый широкополосный член независимо от даты начала и окончания, и предположим, что у вас есть 85 строк где критерии совпадают, вы фактически будете возвращать каждому члену совета 85 раз. Это подчеркивает очень вескую причину для перехода от неявных соединений ANSI 89, которые вы используете, к синтаксису явного соединения ANSI 92. This article подчеркивает некоторые очень веские причины, чтобы сделать переключатель.

Таким образом, ваш запрос стал бы (я должен был угадать ваши имена полей):

SELECT * 
FROM TB_Main arfe 
     INNER JOIN TB_BoardMembersLINK bml 
      ON bml.Entity = arfe.ID 
     INNER JOIN TB_BoardMembers bm 
      ON bm.ID = bml.BoardMemberID 

Следующая вещь, которую я заметил о вашем запросе, что использование функций в предложении где не очень эффективно все, так что из-за этого:

WHERE YEAR(bml.start) <= 2011 
AND  (YEAR(bml.end) >= 2011 OR bml.end IS NULL) 

Вы работаете функцию YEAR дважды для каждой строки, и удаление любой возможный шанс использовать индекс по bml.Start или bml.End (если таковые существуют). Еще раз Aaron Bertrand написал a nice article выделения надлежащей практики при запросе диапазона дат, то цель на SQL-сервере, но принципы остаются теми же, поэтому ваш где положение стало бы:

WHERE bml.Start <= '20110101' 
AND  (bml.End >= '20110101' OR bml.End IS NULL) 
AND  bml.start > 0 

Ваш последний запрос должен затем быть:

SELECT bml.Entity, 
     GROUP_CONCAT(DISTINCT CONCAT(bm.First, ' ', bm.Last, 
      IF (bm.Occupation != '', ' - ', ''), bm.Occupation) 
      SEPARATOR "\n") as Board 
FROM TB_Main arfe 
     INNER JOIN TB_BoardMembersLINK bml 
      ON bml.Entity = arfe.ID 
     INNER JOIN TB_BoardMembers bm 
      ON bm.ID = bml.BoardMemberID 
WHERE bml.Start <= '20110101' 
AND  (bml.End >= '20110101' OR bml.End IS NULL) 
AND  bml.start > 0 
GROUP BY bml.Entity 
ORDER BY Board; 

Example on SQL Fiddle

+0

Благодарим вас за предоставление такого замечательного объяснения! Мне нравится StackOverflow из-за уроков, подобных этому! – jerrygarciuh

0

Если вы читали на GROUP_CONCAT

«Эта функция возвращает результирующую строку с каскадными ненулевыми значениями из группы.»

Здесь, в данном случае, группа кажется всего лишь одной группой, как вы говорите, существует только одна сущность? Я не уверен, так ли это из вашего описания. Почему вы также не группируете имя, фамилию и должность, это может дать вам всех членов.

Я также не уверен, ваши соединения, без реальных данных, его трудно объяснить, что часть, как каждый присоединиться произведения для некоторого набора данных правильно, даже если его не самый лучший способ, чтобы написать запрос

Смежные вопросы