#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 результатов. И я не уверен, решило бы это мою проблему. Порядковый номер главной страницы и дочерней страницы не имеют ничего общего друг с другом. Мне просто нужно получить одну подстраницу каждой главной страницы, которая имеет самый высокий порядковый номер