MySQL получает 2% записи

avatar
Daniel Lee
9 августа 2021 в 06:18
47
1
2

Я пытаюсь получить 2% записи случайной выборки.

SELECT * FROM Orders
ORDER BY RAND()
LIMIT (SELECT CEIL(0.02 * (SELECT COUNT(*) FROM Orders)));

Это выдает синтаксическую ошибку из-за строки 3. Я что-то делаю не так? Или есть лучший способ получить n% записей?

Источник

Ответы (1)

avatar
Tim Biegeleisen
9 августа 2021 в 06:23
3

Если вы используете MySQL 8+, то ROW_NUMBER() предоставляет один вариант:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (ORDER BY RAND()) rn,
              COUNT(*) OVER () cnt
    FROM Orders
)

SELECT *
FROM cte
WHERE 1.0*rn / cnt <= 0.02;

В MySQL 5.7 и более ранних версиях мы можем имитировать номер строки:

SELECT *
FROM
(
    SELECT *, (@rn := @rn + 1) AS rn
    FROM Orders, (SELECT @rn := 0) AS x
    ORDER BY RAND()
) t
CROSS JOIN (SELECT COUNT(*) AS cnt FROM Orders) o
WHERE 1.0*rn / cnt <= 0.02; 
Daniel Lee
9 августа 2021 в 06:29
0

Я думаю, что проще всего использовать ограничение количества записей в 2%. SELECT CEIL(0.02 * (SELECT COUNT(*) FROM Orders)) при независимом запуске дает номер. Интересно, почему это нельзя совместить с limit

Tim Biegeleisen
9 августа 2021 в 06:31
0

@DanielLee Я не уверен, может ли подзапрос появиться внутри предложения LIMIT. В любом случае, версия, которую я использовал, — это то, что я бы предпочел для производственной системы.

Daniel Lee
9 августа 2021 в 06:36
0

Да, я думаю, предел не позволяет подзапрос в конце. Тогда вы можете объяснить COUNT(*) OVER () cnt этот? И я попытался запустить ваш код, и я получаю сообщение об ошибке `ROW_NUMBER() OVER (ORDER BY RAND())`

Tim Biegeleisen
9 августа 2021 в 06:37
0

@DanielLee Похоже, вы используете MySQL 5.7.

Daniel Lee
9 августа 2021 в 06:41
0

@TimBiegeleisen Думаю, да. но проверить версию не могу. В настоящее время я практикую использование базы данных SQL www.w3schools.com.

Tim Biegeleisen
9 августа 2021 в 06:43
0

Я обновил свой ответ версией, которая может работать на вашем MySQL. Надеюсь, понятно, почему мы предпочитаем использовать MySQL 8+ и аналитические функции.

Daniel Lee
9 августа 2021 в 06:44
0

@TimBiegeleisen, отредактированный вариант сработал у меня. Но можешь объяснить COUNT(*) OVER ()? Я понимаю раздел, но не могу понять, почему вы считаете его больше ()

Tim Biegeleisen
9 августа 2021 в 06:47
1

@DanielLee Далее следует OVER — это предложение окна. Для COUNT(*) OVER () с пустым () это просто означает отсутствие окна, которое по умолчанию относится ко всей таблице. Таким образом, выполнение SELECT *, COUNT(*) OVER () AS cnt FROM Orders вернет каждую строку из вашей таблицы плюс новый столбец cnt, который содержит общее количество записей в Orders.

Daniel Lee
9 августа 2021 в 06:49
0

@TimBiegeleisen Это имеет смысл. В качестве альтернативы я могу использовать другой подзапрос `(SELECT COUNT(*) FROM Orders)', правильно? Но ваш выглядит очень аккуратно!

Daniel Lee
9 августа 2021 в 06:51
0

Давайте продолжим обсуждение в чате.