У меня есть таблица базы данных с именем tbl_emails, как это
id email
1 [email protected]
2 [email protected]
3 [email protected]
4 [email protected]
5 [email protected]
6 [email protected]
7 [email protected]
8 [email protected]
9 [email protected]
10 [email protected]
У меня около 5000 строк в таблице. Теперь то, что я хочу сделать, это получить от него 100 писем. Но я хочу, чтобы 80 строк означали 80% DESC и 20% ASC по идентификатору, в настоящее время я делаю это с помощью нескольких запросов и результатов слияния в PHP. Мне интересно, это возможно в одном SQL-запросе?
Спасибо!


Вы можете использовать UNION ALL, чтобы объединить результаты двух запросов с одинаковыми столбцами.
SELECT * FROM (
SELECT id, email
FROM tbl_emails
ORDER BY id ASC
LIMIT 80
) AS top
UNION ALL
SELECT * FROM (
SELECT id, email
FROM tbl_emails
ORDER BY id DESC
LIMIT 20
) AS bottom;
Если вам нужно сохранить порядок строк в выводе, вы можете дополнительно использовать переменные для хранения количества строк в каждом запросе.
set @top := 0;
set @bottom := 0;
SELECT * FROM (
SELECT id, email, @top := @top+1 AS top, @bottom AS bottom
FROM tbl_emails
ORDER BY id ASC
LIMIT 80
) AS top
UNION ALL
SELECT * FROM (
SELECT id, email, @top AS top, @bottom := @bottom + 1 AS bottom
FROM tbl_emails
ORDER BY id DESC
LIMIT 20
) AS bottom
ORDER BY top, bottom;
Нет, это не гарантирует работу и неверно; не гарантируется, что порядок, примененный к производной таблице, будет сохранен в окончательном выборе, внешний выбор всегда требует критерия упорядочивания, чтобы гарантировать порядок.
@Stu В каком случае это не сработает?
в случае, если это фундаментальное свойство множеств, в том, что множества (таблица, производная таблица, табличное выражение и т. д.) не имеют внутреннего порядка; порядок, используемый в производной таблице с ограничением, служит только частью определения возвращаемых строк. Любые предположения о том, что упорядочение будет сохранено в наборе без упорядочения, являются ошибкой, ожидающей своего появления.
И кроме того, если я правильно понимаю OP, действительно важна фильтрация (получить первые 80 и последние 20 строк), а не порядок вывода.
Этот аспект неясен из вопроса ОП.
Это отлично работает для меня как Мои требования. Я не знаю, кто проголосовал против и почему
Я обновил свой ответ, чтобы предоставить более сложный запрос с возможностью сохранения порядка.
используйте оператор UNION ALL, чтобы объединить результаты двух отдельных запросов, которые извлекают требуемый процент электронных писем.
SELECT email
FROM tbl_emails
ORDER BY id DESC
LIMIT (SELECT CEIL(COUNT(*) * 0.8) FROM tbl_emails)
UNION ALL
SELECT email
FROM tbl_emails
ORDER BY id ASC
LIMIT (SELECT CEIL(COUNT(*) * 0.2) FROM tbl_emails);
дайте мне знать, если это может вам помочь
принятый ответ имеет некоторые ненужные накладные расходы/проблемы.
Во-первых, для использования производных таблиц требуются две дополнительные временные таблицы. Это не конец света, но в этом нет необходимости.
Во-вторых, введение deprecatedSetting user variables within expressions просто гарантирует проблему в будущем при удалении этой функциональности.
(
SELECT id, email, 0 AS s
FROM tbl_emails
ORDER BY id ASC
LIMIT 80
)
UNION ALL
(
SELECT id, email, 1 AS s
FROM tbl_emails
ORDER BY id DESC
LIMIT 20
)
ORDER BY s ASC, IF(s = 0, id, NULL) ASC, IF(s = 1, id, NULL) DESC;
В дополнение к комментарию Стью о необходимости заказать внешний выбор, в документах указано:
Использование ORDER BY для отдельных блоков запроса или операторов ничего не говорит о порядке, в котором строки появляются в конечном результате, поскольку строки, созданные операцией набора, по умолчанию неупорядочены.
Добавьте элемент row_number и
order by case when rn <=80 then -rn else rn end?