powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Получить случайную строку из выборки
25 сообщений из 85, страница 1 из 4
Получить случайную строку из выборки
    #39852258
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть таблица с номерами NUMBERS(num,status), в которой содержится 10к записей.
Мне нужно получить из нее один случайный свободный (status=0) номер и закрепить его (status=1) после использования.
Не посоветуете, как лучше всего получить одну случайную запись из выборки?

Решение "в лоб":
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select *
from (
select *
from numbers
where status=0
order by dbms_random.value
)
and rownum=1



Но намного больше мне нравится такой способ:
Код: plsql
1.
2.
3.
4.
select *
from numbers sample(1)
where status=0
and rownum=1


Вот только из документации не могу найти информацию, где определяется, какие записи попадут в sample, и попадут ли они туда до where или после.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852267
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.получить из нее один случайный свободный (status=0) номер и закрепить его (status=1) после использования.
Не туда копаете изначально.
Получить И ЗАКРЕПИТЬ одну запись - курсор select for update skip locked, из которого фетчим одну строку с последующим update where current of.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852268
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

sample_percent
For sample_percent, specify the percentage of the total row or block count to be included in the sample.

.....
stax
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852269
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousAlibek B.получить из нее один случайный свободный (status=0) номер и закрепить его (status=1) после использования.
Не туда копаете изначально.
Получить И ЗАКРЕПИТЬ одну запись - курсор select for update skip locked, из которого фетчим одну строку с последующим update where current of.
Ах да, случайную... Ну отсортируйте табличку посредством insert into ... select from ...order by dbms_random.value, 10к строк - мелочь.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852271
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

он хочет чтоб селект вернул одну "очень" случайную запись

.....
stax
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852272
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.попадут ли они туда до where или после.
До. sample - не фильтр, это часть query_table_expression
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852274
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Staxон хочет чтоб селект вернул одну "очень" случайную запись
ну дык ить и будет "случайная", ежели записи хранятся в хаотичном порядке.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852279
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousStaxон хочет чтоб селект вернул одну "очень" случайную запись
ну дык ить и будет "случайная", ежели записи хранятся в хаотичном порядке.
оно как-бы теоретически без ордер бай и так случайно выбирает, но на практике в более менее постоянном порядке

напр надо разыграть приз (случайному клиенту), если без dbms_random,
то счасливчик буде более менее один и тот же (напр из первого блока)

.....
stax
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852280
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Вот только из документации не могу найти информацию, где определяется, какие записи попадут в sample, и попадут ли они туда до where или после.
из доки

https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#SQLRF01702

sample_clause

The sample_clause lets you instruct the database to select from a random sample of data from the table, rather than from the entire table.

....
stax
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852293
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
create table dropme_t as select rownum num, 0 status from dual connect by level <= 10e3 order by dbms_random.value;
Table created

declare cursor c is select * from dropme_t where status = 0 for update skip locked;
begin 
  for i in c loop dbms_output.put_line('Закреплено: '|| i.num); 
                      update dropme_t set status =1 where current of c; 
                      exit; 
  end loop; 
commit; 
end;
/
Закреплено: 4790
PL/SQL procedure successfully completed

SQL> /
Закреплено: 3112
PL/SQL procedure successfully completed

SQL> /
Закреплено: 2139
PL/SQL procedure successfully completed

SQL> /
Закреплено: 5916
PL/SQL procedure successfully completed

SQL> /
Закреплено: 7492
PL/SQL procedure successfully completed

SQL> 


Staxнапр надо разыграть приз (случайному клиенту)
В этом случае
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
declare l_num number; try integer := 0;
  try_limit constant integer := 100e3;
begin
  loop
    try := try + 1;
    update dropme_t set status = 1 where status = 0 and num = round(dbms_random.value(1,10e3))
    returning num into l_num;
  exit when sql%rowcount = 1;
  exit when try >= try_limit;
  end loop;
  if try < try_limit then
    dbms_output.put_line('Закреплено: '|| l_num);
  else
    dbms_output.put_line('Нишмогла я...');
  end if;
end;
/
Закреплено: 4457
PL/SQL procedure successfully completed

SQL> /
Закреплено: 3832
PL/SQL procedure successfully completed

SQL> /
Закреплено: 5977
PL/SQL procedure successfully completed

SQL> /
Закреплено: 6133
PL/SQL procedure successfully completed

SQL> 
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852304
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousВ этом случае

нету в табличке сквозного num

.....
stax
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852306
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Staxandrey_anonymousВ этом случае

нету в табличке сквозного num
Что это меняет?
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852307
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно, еще раз, для полноты изложения:
- если несколько параллельных процессов должны обрабатывать набор данных, отбирая по одной записи - см. метод с for update skip locled
- если надо всего лишь выбрать пару-тройку "призеров" - то проще всего генерировать случайный ключ и делать probe.
Генерацию ключа можно заменить генерацией случайного rowid, если чуть напрячься и построить карту экстентов таблицы.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852310
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousЧто это меняет?
что кодировать взамест and num = round(dbms_random.value(1,10e3))?

....
stax
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852315
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Staxandrey_anonymousЧто это меняет?
что кодировать взамест and num = round(dbms_random.value(1,10e3))?
Верхнюю и нижнюю границу num.
Для сильно разреженных данных можно либо пронумеровать строки, либо генерировать rowid.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852319
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousВерхнюю и нижнюю границу num.
Для сильно разреженных данных можно либо пронумеровать строки, либо генерировать rowid.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
SQL> update dropme_t set num = num*1000;
10000 rows updated

SQL> create index dropme_t$num on dropme_t(num);
Index created

SQL> 
declare l_num number; try integer := 0;
  try_limit constant integer := 100e5;
begin
  loop
    try := try + 1;
    update dropme_t set status = 1 where status = 0 and num = round(dbms_random.value(1,10e6))
    returning num into l_num;
  exit when sql%rowcount = 1;
  exit when try >= try_limit;
  end loop;
  if try < try_limit then
    dbms_output.put_line('Закреплено: '|| l_num);
  else
    dbms_output.put_line('Нишмогла я...');
  end if;
end;
/
Закреплено: 2803000
PL/SQL procedure successfully completed

SQL> /
Закреплено: 9299000
PL/SQL procedure successfully completed

SQL> /
Закреплено: 6073000
PL/SQL procedure successfully completed
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852346
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

update numbers set status=1 where status=0 and rownum=1
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852347
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-update numbers set status=1 where status=0 and rownum=1
Само собой, только добавить returning into.
Ну тут нет случайности.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852348
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

добавте в вывод колличество спроб

я не спорю и ничего не доказываю

но имхо order by dbms_random.value самый лучий вариант

....
stax
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852351
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сортировать 10к строк, чтобы получить из них одну случайную?
Как-то это выглядит не очень.
Тогда уж лучше вообще не сортировать, а вместо rownum=1 написать rownum=(select count from numbers where status=1)
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852362
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Ну тут нет случайности.В оракле нет штатных средств получения случайности.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852369
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сортировать 10к коротких строк - мелочь, вообще говоря, если не сто-двести-тысячу раз в секунду.
Но Вы так и не озвучили задачу, для решения которой захотелось странного.

Alibek B.вместо rownum=1 написать rownum=(select count from numbers where status=1)
И что будет?
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852405
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Регистрируются клиенты, получают уникальный номер и затем используют этот номер в разных местах.
Если эти номера будут не случайными, а последовательными, то это будет нежелательным. Планируются сценарии типа "подарок каждому сотому клиенту" и последовательная нумерация будет приводить к попыткам манипулирования.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852406
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousИ что будет?
По идее - я выберу не первую строку перемешанной выборки, а случайную строку не перемешанной выборки.
...
Рейтинг: 0 / 0
Получить случайную строку из выборки
    #39852407
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousСортировать 10к коротких строк - мелочь
Не только сортировать - вначале сгенерировать 10к случайных значений, а затем их сортировать.
Сгенерировать одно случайное значение и отфильтровать по нему кажется более оптимальным.
...
Рейтинг: 0 / 0
25 сообщений из 85, страница 1 из 4
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Получить случайную строку из выборки
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]