2009-11-16 5 views
0

в базе данных MS-Access я есть таблицаслучайная сортировка каждый раз, когда запрос выполняется

num weight 
1  12 
4  13 
2  13 
6  9 
7  13 

как я могу написать запрос, который будет сортировать таблицу по весу в порядке убывания. но числа 4, 2 и 7 имеют одинаковый вес (13), поэтому их нужно сортировать случайным образом каждый раз, когда выполняется запрос.

любая помощь оценена.

ответ

2

Как правило, ваш SQL будет содержать случайную функцию некоторого типа (похоже, что для этого функция доступа имеет функцию rnd()).

Таким образом, вы можете использовать:

select num, weight, rnd(num) 
from tbl 
order by weight desc, 3 

Это позволит вам увидеть г для целей тестирования. В реальном запросе, вы можете просто хотите использовать что-то вроде:

select num, weight 
from tbl 
order by weight desc, rnd(num) 

От this page:

Если значение больше 0, Rnd() возвращает следующее случайное число.
Когда значение меньше 0, Rnd() возвращает одно и то же случайное число, основанное на значении. Если значение происходит только один раз, вы не заметите этого поведения. Доступ также сбрасывает семя, что означает, что последовательность начинается снова и снова.
Если значение равно 0, RND() возвращает самое последнее сгенерированное случайное число

Update 1: я не уверен, является ли rnd() выполняется один раз в следующих запросов или один раз в строке - документы не ясны. Комментарии, похоже, указывают, что одни и те же результаты принимаются для всех строк, что указывает на то, что они могут быть последними. Это может быть, что изменение его на rnd(num) или rnd(abs(num)+1) исправит эту проблему. Мне нужно будет проверить, когда я доберусь до коробки с установленным доступом.

Обновление 2: Теперь я проверил это в Access 2007, и он действительно дает одно и то же случайное значение для каждой строки, когда вы используете rnd (1). Это значение делает при каждом запросе запроса, а отдельные строки получают разные значения для rnd(num). Таким образом, запрос вам нужно:

select num, weight from tbl order by weight desc, rnd(num); 

Если вы создаете таблицу с двумя полями Number, а затем запустить этот запрос через него, вы увидите, что постоянное освежать (с F5) обменяет вокруг 2, 7 и 4 строк в случайном порядке, но оставить 1 и 6 строк в том же месте, так как весы первых трех - все 13, а весы последних двух - 12 и 9 соответственно.

Я обновил запросы выше, чтобы соответствовать этой новой информации.

+0

Семя 1 будет генерировать тот же случайный номер факса для каждой записи. Вы могли бы Вместо этого используйте num * weight. – marg

+0

@marg, семя не установлено для положительных чисел, только отрицательные (см. цитату со связанной страницы). rnd (1) будет генерировать другое число каждый раз. Использование num * weight даст вы одинаковый порядок каждый раз, а не то, что хотел OP. – paxdiablo

+0

Марг прав о num * weight. Я получал одинаковое случайное число с rnd (1) – silverkid

0

Я думаю, что это сделает трюк ...

ORDER BY weight, Rnd() 
0

При использовании RND() в Access SQL Database Engine из-за пределы доступа UI, та же последовательность случайных чисел будет использоваться каждой сессией (нет встроенной поддержки Randomize УВЫ).

Например, подключение к источнику затем выполнить SELECT RND(); три раза подряд, вы получите следующие значения:

0.705547511577606 
0.533424019813538 
0.579518616199493 

Закрыть соединение, подключение к источнику снова затем выполнить тот же запрос снова три раза вы получите те же три значения, что и выше, в том же порядке.

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

SELECT RND() 
    FROM T 
WHERE RND() > CDBL(0.6); 

Мы знаем, что первое значение в новой сессии будет 0.705547511577606, поэтому выражение

RND() > CDBL(0.6)

оценит TRUE. Однако значение 0.533424019813538 равно , которое повторяется для каждой строки в таблице T, значение, которое не удовлетворяет пункту WHERE! Поэтому ясно, что значение RND() в предложении WHERE отличается от значения в предложении SELECT. Полный код размещен ниже.

Примечание. Я задавался вопросом, можно ли использовать наименее значимую часть значения CURRENT_TIMESTAMP, генерируя случайное число, которое может использоваться последовательно в рамках одного запроса и не должно быть предсказуемым для сеанса, поскольку RND() есть. Тем не менее, база данных Access Engine не поддерживает его и его ближайший аналог, функция NOW(), не имеет достаточной детализации, чтобы быть полезным :(

Sub jmgirpjpo() 

    On Error Resume Next 
    Kill Environ$("temp") & "\DropMe.mdb" 
    On Error GoTo 0 

    Dim cat 
    Set cat = CreateObject("ADOX.Catalog") 

    With cat 

    .Create _ 
     "Provider=Microsoft.Jet.OLEDB.4.0;" & _ 
     "Data Source=" & _ 
     Environ$("temp") & "\DropMe.mdb" 

    With .ActiveConnection 

     .Execute "CREATE TABLE T (T INT);" 
     .Execute "INSERT INTO T VALUES (1);" 
     .Execute "INSERT INTO T VALUES (2);" 
     .Execute "INSERT INTO T VALUES (3);" 

     Dim rs 
     Set rs = .Execute("SELECT RND() FROM T WHERE RND() > CDBL(0.6);") 
     MsgBox rs.GetString 

    End With 
    End With 

End Sub 
+0

Можете ли вы передать значение столбца извне Jet/ACE, т. Е. Rnd (num) в примере исходной таблицы? –

+0

Да, но это не изменит его начальное значение. – onedaywhen

Смежные вопросы