Выберите количество всех дочерних строк в MySQL

У меня есть таблица MySQL articles, в которой я организовал содержимое в следующей иерархии:

  1. Раздел
  2. Тема
  3. Глава
  4. Сообщение

Каждый элемент из вышеперечисленного находится в строке с полями: id, parent, name и т. д.

Строка сообщения parent соответствует строке главы id, строка главы parent соответствует строке темы id, а строка темы parent соответствует строке раздела id.

У меня нет более высокой иерархии, чем выше.

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

Мой брат помог мне со следующим запросом на выборку. Однако он относительно медленный - ~ 0,6 секунды.

SELECT
    subjects.id,
    subjects.name,
    subjects.link,
    (
    SELECT
        COUNT(DISTINCT posts.id)
    FROM
        articles AS chapters,
        articles AS posts
    WHERE
        chapters.parent = subjects.id AND(
            posts.parent = chapters.id OR posts.parent = subjects.id
        )
    ) AS child_count
FROM
    articles AS subjects
WHERE
    subjects.parent = 62

Мне нужна помощь в улучшении производительности, пожалуйста.

Большое спасибо!!

Возможный дубликат Как создать иерархический рекурсивный запрос MySQL

Madhur Bhaiya 06.07.2019 06:00

Если он медленный, то вы, вероятно, забыли создать показатель на parent.

Andreas 06.07.2019 06:01

Вы сказали "строка поста parent равна строке главы id", так почему posts.parent = subjects.id? Это никогда ничего не сопоставит, поскольку тема не может быть родителем сообщения.

Andreas 06.07.2019 06:03

вау, только что добавил индекс в родительский столбец. и теперь он обрабатывается за 0,02 секунды @Andreas, спасибо !!

Irfanullah Jan 06.07.2019 06:07

Что касается этого posts.parent = subjects.id Я думаю, что мы должны были добавить это, потому что иначе он учитывал только сообщения. Мне также нужно было подсчитать строки глав. Несмотря на то, что он говорит posts.parent, на самом деле это строка главы, потому что родитель является предметом. Странно, как работает запрос, лол @Andreas

Irfanullah Jan 06.07.2019 06:12

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

Irfanullah Jan 06.07.2019 06:16
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
6
465
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Этой логике трудно следовать, но я думаю, что вы намереваетесь:

SELECT s.id, s.name, s.link,
       ( (SELECT COUNT(*)  -- count children
          FROM articles c
          WHERE c.parent = s.id
         ) +
         (SELECT COUNT(*)  -- count grandchildren
          FROM articles c JOIN
               articles p
               ON p.parent = c.id
          WHERE c.parent = s.id
         )
    ) as child_count
FROM articles s
WHERE s.parent = 62;

Затем для этого запроса вам нужен индекс articles(parent).

Примечания:

  • Никогда используйте запятые в предложении FROM.
  • Всегда использует правильный, явный синтаксис стандартныйJOIN. Твоему брату тоже нужно научиться правильно писать SQL.
  • COUNT(DISTINCT) может быть дороже, чем просто COUNT().
  • ORs в корреляции или предложении ON могут помешать оптимизатору.

работает отлично и занимает 0,015 секунды ... спасибо :)

Irfanullah Jan 06.07.2019 17:34

Другие вопросы по теме