2012-05-09 2 views
0

У меня есть таблица, где данные могут выглядеть так:Сортировка случайным образом с группировкой в ​​PostgreSQL

ID | PARENT_ID | several_columns_to_follow 
---+-----------+-------------------------- 
1 |   1 | some data 
2 |   2 | ... 
3 |   1 | ... 
4 |   4 | ... 
5 |   3 | ... 
6 |   1 | ... 
7 |   2 | ... 
8 |   3 | ... 

в соответствии с требованиями, мне нужно, чтобы сортировать двумя способами (по запросу пользователя):

1) Случайный порядок идентификаторов в последовательных родителей - это легко достигается с

SELECT * FROM my_table ORDER BY parent_id, random() 

2) Случайный порядок идентификаторов в пределах случайным образом отсортированных родителей - и это, где я застрял. Очевидно, что просто сортировка всего на random() будет не очень полезной.

Любые предложения? В идеале, в одном выражении SQL, но я готов пойти на более чем один, если необходимо. Объем данных невелик, поэтому я не беспокоюсь о производительности (в конечном итоге не будет больше 100 строк).

ответ

0

Может быть, это будет делать:

ORDER BY ((parent_id * date_part('microseconds', NOW()) :: Integer) % 123456), 
((id * date_part('microseconds', NOW()) :: Integer) % 123456); 

Может быть простое число вместо 123456 будет получить «более случайные» результаты

+0

Точно. Было бы неплохо, что для такого рода вещей была некоторая параметризованная хеш-функция. – wildplasser

+0

Да, это в значительной степени то, что мне нужно. И, да, использование крупнотонкой первичной доходности дает лучшие результаты. Я использовал 391939 в моем случае (просто случайное 6-значное простое число - каламбур не предназначен). –

+0

Просто для удовольствия любая идея о том, как псевдослучайно сортировать таблицу со 100 000 000 записей за время, подходящее для веб-приложения? Скажем, менее 2 секунд? –

0

random() действительно является неприятной функцией в конечном сортировке. Если почти случайное достаточно хорошо, может быть, вы могли бы сортировать по некоторым хешировано вверх зависимости от значений строк, как

SELECT * FROM my_table 
ORDER BY parent_id, (id *12345) % 54321 
    ; 
+0

К сожалению, это не дало бы мне, что я после. Мне нужно каждый раз получать (или, по крайней мере, почти) разный порядок сортировки каждый раз, когда я запрашиваю одни и те же данные. То есть, не меняя данные, порядок сортировки должен измениться. Поэтому сортировка не может опираться ни на что в строке или на любое другое статическое значение. Это действительно должно быть случайным. И, кстати, почему это «противно»? Мы используем эту сортировку в сотнях мест в системе, которая работает много лет. –

+0

Вы можете добавить термин, полученный из текущего времени? Отвратительный в том смысле, что random() нестабилен (Duh) и что окончательный sort ** должен иметь место (порядок в результатах из подзапросов игнорируется). Например: попробуйте использовать функцию rand() в качестве функции сравнения для qsort(). – wildplasser

0

Если это не более 100 записей, имеет смысл просто выбрать все записи, поместить их в локальную таблицу (или в структуру данных памяти на вашем конце клиента) и просто выполнить правильный Fisher-Yates shuffle.

0

Что-то вроде этого следует сделать это:

WITH r AS (SELECT id, random() as rand FROM my_table ORDER BY rand) 
SELECT m.* FROM r JOIN my_table m USING (id) 
    ORDER BY r.rand, random(); 
Смежные вопросы