Получение первого результата ВНЕШНЕГО СОЕДИНЕНИЯ СЛЕВА

#php #mysql #greatest-n-per-group

#php #mysql #наибольшее число пользователей на группу

Вопрос:

У меня есть этот запрос для получения всех основных страниц и вложенных страниц этой страницы. Я использую этот запрос, а затем разделяю страницы позже, проверяя, есть ли у страницы parent_id.

(разница между главной страницей и вложенной страницей заключается в том, что главная страница имеет parent_id равный 0, а вложенная страница > 0)

 SELECT name, url_name, parent_id
FROM pages WHERE active = '1' AND visible = '1' AND deleted = '0'
AND ( parent_id = 0 OR parent_id = " . $main_page['id'] . ")
ORDER BY order_number DESC, id ASC
  

Теперь мне нужно получить ПЕРВУЮ подстраницу (путем упорядочивания по order_number) для каждой главной страницы.

Как бы я это сделал?

Заранее спасибо.

Комментарии:

1. Как вообще работает этот запрос? Вы не определяете псевдоним p в своем операторе FROM .

2. Извините, сообщение было отредактировано. $main_page[‘id’] — текущий идентификатор главной страницы

3. Я думаю, это будет зависеть от определения «ПЕРВОЙ» подстраницы. Что именно делает подстраницу первой? Самый низкий / самый высокий идентификатор? Какой-то другой столбец?

4. Мне нужно упорядочить его по order_number подстраницы

Ответ №1:

 SELECT * FROM pages 
WHERE id IN (
    SELECT max(id) FROM pages
    WHERE aive = '1' AND visible = '1' AND deleted = '0'
    GROUP BY parent_id
)
  

Ответ №2:

попробуйте что-то вроде :

 SELECT p1.name, p1.url_name, p1.parent_id, p2.id, p2.name, p2.url_name
FROM pages p1
LEFT OUTER JOIN pages p2
ON p2.parent_id = p1.id
WHERE p1.parent_id = 0
GROUP BY p1.id
ORDER BY p2.order_number ASC, p1.id ASC
  

Ответ №3:

Это лучше всего решается в MySQL как объединение с исключением. Это очень похоже на многие вопросы, ответы на которые даны под тегом greatest-n-per-group в StackOverflow.

 SELECT p.name, p.url_name
FROM pages p
LEFT OUTER JOIN pages p2 ON p.order_number > p2.order_number
  AND (p2.parent_id, p2.active, p2.visible, p2.deleted) = ({$main_page["id"], 1, 1, 0) 
WHERE (p.parent_id, p.active, p.visible, p.deleted) = ({$main_page["id"]}, 1, 1, 0)
AND p2.id IS NULL;
  

Это решение ищет строку, p2 которая имеет меньший order_id и в остальном соответствует тем же условиям, что и p . Если такая строка нижнего порядка не найдена, то p должна иметь наименьший order_id из тех строк в той же группе, которые соответствуют условию, то есть строки с одинаковым parent_id.

Если у вас есть составной индекс (parent_id, активный, видимый, удаленный, order_id), это должен быть очень эффективный запрос.

Одна часть этого решения, которую вы, возможно, не ожидаете, заключается в том, что вам нужно повторить условия внутри критериев left join.


Я отредактировал приведенный выше запрос после его тестирования. Теперь это должно работать лучше. Обратите внимание, что это не сравнение order_number подстраницы с order_number ее родительского элемента — это сравнение order_number подстраницы с порядковым номером ее братьев и сестер, т.Е. подстраниц одного и того же родителя.

Комментарии:

1. Это возвращает 0 результатов. И я не уверен, решило бы это мою проблему. Порядковый номер главной страницы и дочерней страницы не имеют ничего общего друг с другом. Мне просто нужно получить одну подстраницу каждой главной страницы, которая имеет самый высокий порядковый номер