Выберите случайную выборку результатов из результата запроса - PullRequest
55 голосов
/ 09 апреля 2009

Этот вопрос задает вопрос о получении случайной (ish) выборки записей на SQL Server, и ответом было использование TABLESAMPLE. Есть ли эквивалент в Oracle 10?

Если нет, есть ли стандартный способ получить случайную выборку результатов из набора запросов? Например, как можно получить 1000 случайных строк из запроса, который обычно возвращает миллионы?

Ответы [ 8 ]

69 голосов
/ 09 апреля 2009
SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        ORDER BY
                dbms_random.value
        )
WHERE rownum <= 1000
62 голосов
/ 20 сентября 2012

Предложение SAMPLE даст вам случайный процент выборки для всех строк в таблице.

Например, здесь мы получаем 25% строк:

SELECT * FROM emp SAMPLE(25)

Следующий SQL (с использованием одной из аналитических функций) даст вам случайную выборку определенного числа каждого вхождения определенного значения (аналогично GROUP BY) в таблице.

Здесь мы выбираем 10 из каждого:

SELECT * FROM (
SELECT job, sal, ROW_NUMBER()
OVER (
PARTITION BY job ORDER BY job
) SampleCount FROM emp
)
WHERE SampleCount <= 10
11 голосов
/ 26 августа 2013

Это не идеальный ответ, но производительность будет намного лучше.

SELECT  *
FROM    (
    SELECT  *
    FROM    mytable sample (0.01)
    ORDER BY
            dbms_random.value
    )
WHERE rownum <= 1000

Пример даст вам процент от вашей фактической таблицы, если вы действительно хотите 1000 строк, вам нужно будет отрегулировать это число. Чаще всего мне просто нужно произвольное количество строк, чтобы не ограничивать свои результаты. В моей базе данных с 2 миллионами строк я получаю 2 секунды против 60 секунд.

select * from mytable sample (0.01)
6 голосов
/ 19 февраля 2015
SELECT * FROM TABLE_NAME SAMPLE(1)

даст вам приблизительно 1%, а не 1/100 от количества наблюдений. Вероятная причина в том, что Oracle генерирует случайный флаг для каждого наблюдения относительно того, включать ли его в выборку, которую он генерирует. Аргумент 1 (1%) в таком процессе генерации принимает роль вероятности того, что каждое наблюдение будет выбрано в выборку.

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

3 голосов
/ 25 июня 2014

Функция выборки используется для выборки данных в ORACLE . Таким образом, вы можете попробовать так: -

SELECT * FROM TABLE_NAME SAMPLE(50);

Здесь 50 - процент данных, содержащихся в таблице. Так что если вы хотите 1000 строк из 100000. Вы можете выполнить запрос как:

SELECT * FROM TABLE_NAME SAMPLE(1);

Надеюсь, это поможет вам.

2 голосов
/ 23 августа 2016

Я знаю, что на этот вопрос уже получен ответ, но, увидев здесь столько посещений, я бы хотел добавить одну версию, которая использует предложение SAMPLE, но все же позволяет сначала фильтровать строки:

with cte1 as (
    select *
    from t_your_table
    where your_column = 'ABC'
)
select * from cte1 sample (5)

Обратите внимание, что для базового выбора требуется столбец ROWID, что означает, что он может не работать, например, для некоторых представлений.

0 голосов
/ 01 мая 2013

Нам было дано задание выбрать только две записи из списка агентов. Т.е. 2 случайных записи для каждого агента в течение недели и т. Д. .... и ниже это то, что мы получили, и это работает

with summary as (
Select Dbms_Random.Random As Ran_Number,
             colmn1,
             colm2,
             colm3
             Row_Number() Over(Partition By col2 Order By Dbms_Random.Random) As Rank
    From table1, table2
 Where Table1.Id = Table2.Id
 Order By Dbms_Random.Random Asc)
Select tab1.col2,
             tab1.col4,
             tab1.col5,
    From Summary s
 Where s.Rank <= 2;
0 голосов
/ 30 апреля 2012

Примерно так должно работать:

SELECT * 
FROM table_name
WHERE primary_key IN (SELECT primary_key 
                      FROM
                      (
                        SELECT primary_key, SYS.DBMS_RANDOM.RANDOM 
                        FROM table_name 
                        ORDER BY 2
                      )
                      WHERE rownum <= 10 );
...