Каков наиболее эффективный способ выбрать все данные из таблицы «многие ко многим»?

Я разработал таблицу многие ко многим ниже:

activity
----------
id
name
activity_student
----------
id
activity_id
student_id
student
----------
id
name

Каждый учащийся может участвовать во многих мероприятиях, и в каждом мероприятии может быть много участников.

И я хочу выбрать из активности, и в то же время я хочу собрать участников как массив.

Окончательные данные, которые я хочу сделать, выглядят так:

[
  id => 1,
  name => football club activity,
  participants =>
    [
      [
        id => 1,
        name => example student,
        class => 3
      ],
      [
        id => 3,
        name => example student2,
        class => 5
      ]
    ]
]

Я попытался выбрать activity.* и group_concat для student_id. А затем я получил данные студента, используя оператор foreach.

Но я думаю, что это не лучшая практика, так как время запроса стало больше 10 секунд с более чем 10 000 строк.

Какова наилучшая практика?

  • Я использую базу данных CI4, mysql с движком InnoDB.

person tonynamy    schedule 03.01.2020    source источник
comment
В грубом приближении, при обработке данных в PHP (и при отсутствии каких-либо других агрегирующих функций) вам никогда не понадобится функция GROUP_CONCAT. Присоединений будет достаточно. См. stackoverflow.com/questions/57359481/ для чего-то подобного   -  person Strawberry    schedule 03.01.2020
comment
Какова ваша метрика для наиболее эффективного способа? Самый быстрый? Самый компактный? Лучше всего использовать в любой следующей задаче? Легче всего читать? (Этот пример из 17 строк JSON с треском проваливается на некоторых из них.)   -  person Rick James    schedule 06.01.2020
comment
@RickJames Я имел в виду способ использовать самые низкие вычислительные ресурсы. Я думаю, что мой источник неэффективен, потому что я много раз звоню в БД.   -  person tonynamy    schedule 07.01.2020


Ответы (1)


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

Читать о JOIN.

SELECT  a.name AS ActivityName,
        s.name AS StudentName,
        ...
    FROM activity AS a
    JOIN activity_student AS map  USING(activity_id)
    JOIN student AS s  USING(student_id)
    WHERE ...

Вы получаете обратно табличную структуру с именем ActivityName, StudentName и т. д. В WHERE вы можете отфильтровать одно действие или что-то еще.

Советы по эффективной схеме сопоставления: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table

person Rick James    schedule 07.01.2020