Использование cte для получения случайной записи - PullRequest
0 голосов
/ 13 июля 2020

Я нашел следующий код, который отлично работает. Может ли кто-нибудь предложить способ интеграции таблицы местоположений в cte, чтобы я получал случайный location_id с каждой строкой. Я подозреваю, что мне нужен еще один союз, но я не уверен, как получить случайный location_id

В этом примере таблица местоположений упорядочена последовательно для облегчения публикации, но это не всегда будет иметь место.

 CREATE TABLE schedule_hdr AS
SELECT level AS schedule_id,
   'Schedule ' || level AS schedule_name

 FROM   dual
CONNECT BY level <= 2;

CREATE TABLE locations AS
 SELECT level AS location_id,
   'Door ' || level AS location_name,

CASE round(dbms_random.value(1,3)) 
        WHEN 1 THEN 'A' 
        WHEN 2 THEN 'T' 
        WHEN 3 THEN 'G' 
     END AS location_type

FROM   dual
CONNECT BY level <= 25;


 ALTER TABLE locations 
     ADD ( CONSTRAINT location_id_pk
   PRIMARY KEY (location_id));



WITH random_times (     schedule_id,    datetime, lvl ) AS (
 SELECT schedule_id,
      TRUNC(sysdate)
      + 
 NUMTODSINTERVAL( FLOOR(DBMS_RANDOM.VALUE(0,23*60)), 'MINUTE' ),
     1
FROM   schedule_hdr
 UNION ALL
SELECT schedule_id, 
     datetime + NUMTODSINTERVAL(FLOOR(DBMS_RANDOM.VALUE(6,11)), 'MINUTE'),
     lvl + 1
FROM   random_times
WHERE  lvl < 5
)
SELECT schedule_id,
   datetime
FROM   random_times
ORDER BY schedule_id, datetime;

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Вот что вы хотите:

WITH random_times (     schedule_id,    datetime, lvl ) AS (
 SELECT schedule_id,
      TRUNC(sysdate)
      + 
 NUMTODSINTERVAL( FLOOR(DBMS_RANDOM.VALUE(0,23*60)), 'MINUTE' ),
     1
FROM   schedule_hdr
 UNION ALL
SELECT schedule_id, 
     datetime + NUMTODSINTERVAL(FLOOR(DBMS_RANDOM.VALUE(6,11)), 'MINUTE'),
     lvl + 1
FROM   random_times
WHERE  lvl < 5
)
SELECT
   schedule_id,
   datetime,
   loc.*
FROM   random_times
      ,locations loc
where loc.location_id = (
          select location_id
          from locations
          -- you need this predicate to disable subquery caching:
          where location_id*0 = schedule_id*0+lvl*0
          order by dbms_random.value()
          fetch first 1 row only
       )
ORDER BY schedule_id, datetime;
0 голосов
/ 13 июля 2020

Сложно понять, что происходит из этого фрагмента кода, но если вы хотите заполнить новые таблицы данными в случайном порядке из базовых таблиц, в которых есть данные, вы можете подумать о генерации случайных значений, а затем упорядочении row_number ими, чтобы получить псевдо-первичный ключ (целое число, с увеличением):

SELECT 
  t.*,
  row_number() over(order by dbms_random.value(1,10)) as pseudopk 
FROM
  table

Например, у вас есть базовые таблицы данных (или cte), например:

BasePerson
Name, Age
--------
John, 20
Mary, 30

BaseAddress
City
----
New York
Paris
Berlin

INSERT INTO RealAddress(ID, City)
SELECT * FROM
(
  SELECT row_number() over(order by dbms_random.value(1,10)) pk, a.City 
  FROM BaseAddress
)
WHERE pk < 3 --2 people need 2 address

INSERT INTO RealPerson(ID, Name, Age, AddressID)
SELECT pk, Name, Age, pk
FROM(
  SELECT 
    row_number() over(order by dbms_random.value(1,10)) pk, 
    a.Name, 
    a.Age
  FROM BasePerson
)

Это не действительно имеет значение, что мы повторно используем число как для идентификатора человека, так и для его идентификатора адреса, потому что данные адреса были рандомизированы, когда они были вставлены, так что это «люди в случайном порядке относительно их pk, связанные с адресами в случайном порядке относительно адрес pk "

...