MySQL Select Query 80% DESC и 20% ASC

У меня есть таблица базы данных с именем 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-запросе?

Спасибо!

Добавьте элемент row_number и order by case when rn <=80 then -rn else rn end ?

Stu 14.08.2023 10:14
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
3
1
68
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Вы можете использовать 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 14.08.2023 10:20

@Stu В каком случае это не сработает?

Halibut 14.08.2023 10:26

в случае, если это фундаментальное свойство множеств, в том, что множества (таблица, производная таблица, табличное выражение и т. д.) не имеют внутреннего порядка; порядок, используемый в производной таблице с ограничением, служит только частью определения возвращаемых строк. Любые предположения о том, что упорядочение будет сохранено в наборе без упорядочения, являются ошибкой, ожидающей своего появления.

Stu 14.08.2023 10:29

И кроме того, если я правильно понимаю OP, действительно важна фильтрация (получить первые 80 и последние 20 строк), а не порядок вывода.

Halibut 14.08.2023 10:30

Этот аспект неясен из вопроса ОП.

Stu 14.08.2023 10:31

Это отлично работает для меня как Мои требования. Я не знаю, кто проголосовал против и почему

Manisha 14.08.2023 10:51

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

Halibut 14.08.2023 10:56

используйте оператор 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 для отдельных блоков запроса или операторов ничего не говорит о порядке, в котором строки появляются в конечном результате, поскольку строки, созданные операцией набора, по умолчанию неупорядочены.

Вот db<>рабочий пример

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