Итак, эта таблица будет служить примером того, с чем я работаю. Эта таблица состоит из имени кого-то и порядка, в котором они находятся по сравнению с другими:
Моя цель состоит в том, чтобы взять числа в ORDER и переставить их случайным образом и обновить это в таблице, сохраняя записи NAME в том же положении, в котором они были изначально.
Пример желаемого результата:
Используя приведенную выше таблицу, я пробовал следующие решения:
#1
Update TEST_TABLE
Set ORDER = dbms_random.value(1,4);
Это привело к случайным числам от 1 до 4 включительно, но числа могли повторяться, поэтому ORDER мог иметь одно и то же число несколько раз.
Пример попытки решения:
#2
Update TEST_TABLE
Set ORDER = (Select dbms_random.value(1,4) From dual);
Это привело к тому, что одно и то же случайное число было скопировано в каждую запись ORDER, поэтому, если получилось число 3, оно изменит их все на 3.
Пример попытки решения:
Это моя первая публикация в StackOverflow, и я относительно новичок в Oracle, поэтому, надеюсь, я правильно задал этот вопрос.
@HimanshuKandpal Может быть, это была плохая формулировка с моей стороны. Я имел в виду, что хотел только обновить значения в ORDER. Новые значения должны быть случайным числом от 1 до 4, и это число не может быть одинаковым в разных строках. Необходимо обновить только столбец ORDER, а не столбец NAME.
Что такое первичный ключ в таблице? НАЗВАНИЕ, ПОРЯДОК, НАЗВАНИЕ и ПОРЯДОК или что-то другое?
@JonHeller Мне нужно было просто использовать идентификатор вместо имени для примера, но для простоты имя будет pk в этом примере
Как насчет этого?
Образец данных:
SQL> select * from test order by rowid;
NAME C_ORDER
---- ----------
Zac 1
Jeff 2
Bart 3
Kate 4
Таблица обновляется на основе значения, полученного аналитической функцией row_number
, которая сортирует данные случайным образом; совпадения находятся по значению rowid
:
SQL> merge into test a
2 using (with counter (cnt) as
3 (select count(*) from test)
4 select t.rowid rid,
5 row_number() over(order by dbms_random.value(1, c.cnt)) rn
6 from counter c cross join test t
7 ) b
8 on (a.rowid = b.rid)
9 when matched then update set
10 a.c_order = b.rn;
4 rows merged.
Результат:
SQL> select * from test order by rowid;
NAME C_ORDER
---- ----------
Zac 3
Jeff 4
Bart 1
Kate 2
SQL>
Как насчет этого?
MERGE INTO test d USING
(SELECT rownum AS new_order,
name
FROM (SELECT *
FROM test
ORDER BY dbms_random.value)) s
ON (d.name = s.name)
WHEN matched THEN
UPDATE
SET d.sort_order = s.new_order;
Новый порядок создается путем простой сортировки исходных данных по случайным значениям и использования rownum
для нумерации этих случайных записей от 1 до N.
Я использую NAME
для сопоставления записей, но вы должны использовать первичный ключ или rowid
, как в ответе Littlefoot.
Или хотя бы индексированный столбец (для скорости, когда в таблице много данных), который однозначно идентифицирует строку.
В реальной таблице, с которой я работаю, у нее есть pk, который я использую, и я должен был поместить его вместо имени в примере. Но это, кажется, решает мою проблему. Вы, ребята, все потрясающие!
Самый простой — отсортировать данные случайным образом и объединить их в столбце «имя»:
merge into data dst
using (
select rownum as rn, name from (
select name from data order by dbms_random.value()
)
) src
on (src.name = dst.name)
when matched then
update set ord = src.rn
;
Не могли бы вы сообщить нам, что вы подразумеваете под «сохранением записей NAME в том же положении, в котором они были изначально». данные возвращаются запросом или так они хранятся в БД. В Oracle, если вы хотите, чтобы данные отображались, всегда лучше указать предложение ORDER BY, а также данные не хранятся в каком-либо определенном порядке в БД.