group_concat в двух разных таблицах дает одинаковый результат во второй таблице

рассматривать три объекта как студент, курс, предмет Ниже приведены ассоциации -

student has_many courses,
student has_many subjects.

Теперь я хочу получить записи о студентах с именами предметов и названиями курсов, используя mysql group_concat, left join по курсам, left join по предметам и group_by student_id.

Проблема в том, что group_concat('subjects.name') as subject_names дает мне повторяющиеся записи тем, но group_concat('students.name') as student_names дает уникальные имена.

Почему ??


person Sandip Ransing    schedule 07.03.2012    source источник


Ответы (3)


Два левых соединения - это умножение строк на декартово произведение дочерних строк на учащегося.

Пример

  • Студент 1 изучает 3 курса и 2 предмета
  • Создает 6 рядов для ученика 1
  • Дает одно course значение для каждого предмета = каждый курс повторяется дважды
  • Дает одно subject значение за курс = каждый предмет повторяется трижды

Чинить:

Вариант 1. Используйте GROUP_CONCAT(DISTINCT ...) в соответствии с документами MySQL

В MySQL вы можете получить сцепленные значения комбинаций выражений. Чтобы исключить повторяющиеся значения, используйте предложение DISTINCT.

Вариант 2. Используйте производную таблицу UNION ALL +

SELECT
    Student, MAX(CourseConcat), MAX(SubjectConcat)
FROM
    (
    -- 2 separate SELECTs here
    .. student LEFT JOIN course ...
    UNION ALL
    .. student LEFT JOIN subjects...
    ) T
GROUP BY
   Student

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

person gbn    schedule 07.03.2012
comment
спасибо за подробный ответ. Теперь понял, как внутренне работает group_concat на двух разных таблицах. - person Sandip Ransing; 07.03.2012

Следуя вашей логике, group_concat('subjects.name') as subject_names дает вам повторяющиеся записи, потому что для каждого ученика может быть более 1 предмета, поэтому вы получаете дублирующую запись для каждой записи ученика в таблице subject, в то время как group_concat('students.name') as student_names (я полагаю) имеет 1 запись на ученика.

person DarkAjax    schedule 07.03.2012
comment
не на самом деле .. у меня нет дубликатов записей в отношении has_many. всегда есть уникальный предмет и курс, связанный со студентом. - person Sandip Ransing; 07.03.2012

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

Решение GROUP_CONCAT(DISTINCT ...), как указал gbn, великолепно, пока у вас действительно не будет несколько равных или почти равных значений, таких как á и a.

Я исключил ключевое слово из запроса и решил проблему с PHP. Если вам нужно только отличить á от a, простое array_unique сделает свое дело.

К сожалению, мне не повезло, и у меня были точно такие же ценности, которые мне нужно было сохранить. Рассмотрим примеры значений, возвращаемых из поля group_concat запроса к базе данных, разбитого на массив:

$values = array( 'Value1','Value1','Value2','Value2','Value2','Value2' );

Теперь как-нибудь различите, с каким количеством дубликатов вы имеете дело. Я сделал следующее:

$x=0;
$first = reset($values);
while($first === $values[$x]) $x++;

Вышеупомянутое решение работает только в том случае, если ваше фактическое первое и второе значения никогда не совпадают, что в моем случае было правдой. Если это не так, придумайте другой способ узнать, с каким количеством дубликатов вы имеете дело. Наконец, просто отключите все дополнительные значения с помощью модуля:

foreach($values as $k => $v){
       if($k%$x !== 0) unset($values[$k]);
}

Вот и все. Печать значений $ сейчас даст вам:

Array
(
    [0] => Value1
    [2] => Value2
    [4] => Value2
)
person ruuter    schedule 15.02.2015