2016-03-21 3 views
0

В моем случае я использую встроенную базу данных H2, но моя проблема на самом деле является общим SQL-кодом.Выбор записей таблицы в псевдослучайном порядке

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

CREATE TABLE test (id NUMBER, data VARCHAR, reference NUMBER) ; 
INSERT INTO test (id, data) 
SELECT x, 'P'||x FROM system_range(0, 9); 
UPDATE test SET reference = 2 where id = 4; 
UPDATE test SET reference = 4 where id = 6; 
UPDATE test SET reference = 1 where id = 7; 
UPDATE test SET reference = 8 where id = 9; 

SELECT * FROM test ORDER BY id; 

ID DATA REFERENCE 
---------------------------------- 
0 P0  null 
1 P1  null 
2 P2  null 
3 P3  null 
4 P4  2 
5 P5  null 
6 P6  4 
7 P7  1 
8 P8  null 
9 P9  8 

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

Одна вещь, которая будет работать, будет SELECT * FROM test ORDER BY reference, RAND(), но для меня это не кажется случайным, поскольку он всегда будет выбирать все записи без ссылок, которые сначала уменьшают уровень случайности.

Скажите, что хороший и действительный результат, холодный, должен быть ниже.

ID DATA REFERENCE 
---------------------------------- 
8 P8  null 
2 P2  null 
1 P1  null 
4 P4  2 
3 P3  null 
9 P9  8 
5 P5  null 
6 P6  4 
0 P0  null 
7 P7  1 

Я бы предпочел чистое решение SQL, но дает H2 легко расширить, я бы не кончатся создания пользовательской функции, подвергая свой собственный метод Java.

ОБНОВЛЕНИЕ Это не дубликат How to request a random row in SQL, потому что:

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

Почему не читают записи в клиент, и затем ранжировать его? –

+0

Возможно, это будет мой путь, если я не смогу его решить, используя только SQL. Однако я не хочу выходить из чистого SQL-решения. – Julian

+1

Возможный дубликат [Как запросить случайную строку в SQL?] (Http://stackoverflow.com/questions/19412/how-to-request-a-random -row-in-sql) – Bulat

ответ

1

Ну вы никогда не должны говорить никогда прежде чем вы действительно копать немного дальше. Когда я добавил свой комментарий к Jim, я действительно спросил себя, есть ли H2 с Иерархическими запросами Oracle. И, конечно, есть кое-что, как описано в документации H2 под передовой части H2 recursive queries

Так вот есть мой рабочий запрос, который в значительной степени удовлетворяет мое требование:

WITH link(id, data, reference, sort_val, level, tree_id) AS (
    -- Each tree root starts with a random sorting value up to half the number of records. 
    -- This half the number of records is not really needed it can be a hard coded value 
    -- I just said half to achieve a relative uniform distribution of three ids 
    -- take the id of the starting row as a three id 
    SELECT id, data, reference, round(rand()*(select count(*) FROM test)/2) AS sort_val, 0, id FROM test WHERE reference IS NULL 

    UNION ALL 

    -- Increase the sort value by level for each referencing row 
    SELECT test.id, test.data, test.reference, link.sort_val + (level + 1) AS sort_val, level + 1, link.tree_id 
     FROM link 
     JOIN test ON link.id = test.reference 
) 
-- sort value, level and tree id are printed here just to make it easier to understand how it works 
SELECT id, data, reference, sort_val, level, tree_id 
    FROM link 
ORDER BY sort_val; 
Смежные вопросы