2014-12-12 2 views
1

В основном я пытаюсь создать какой-то «алгоритм» для выбора строк из таблицы.RAND() по определенным критериям

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

Так что теперь поставить это код условие:

SELECT 
    * 
FROM 
    people 
ORDER BY 
    RAND() 
LIMIT 
    40 

Затем я хочу, чтобы добавить какое-то «алгоритм» такой запрос, который делает что-то вроде этого, но в MySql

$rand = rand(4,100); 
if($rand == 26) { 
    //the option is now open to potentially scoop those rare people which have the ID of `15256` and `884` 
} 
+0

Пожалуйста, объясните лучше, что вы пытаетесь сделать. Например, что означает «очень-очень редко». –

+0

@GordonLinoff в простых терминах, у меня есть 2 определенных строки в таблице, которые я не хочу, чтобы RAND() очень часто хватался – Curtis

ответ

1

I сказал бы: использование ORDER BY RAND() - плохая идея в целом, потому что она будет оказывать огромное влияние на производительность. Это общеизвестный факт, поскольку RAND() будет оцениваться «на лету» и поэтому не будет использовать индекс для этих значений.

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

SELECT 
    id, 
    name 
FROM 
    (SELECT 
    pool.id AS id, 
    name, 
    IF(rare_ids.id IS NULL, 1, 1/@probability_divisor) AS probability, 
    RAND() AS random 
    FROM 
    pool 
    LEFT JOIN 
    (SELECT 3 AS id 
     UNION ALL 
    SELECT 7 AS id) AS rare_ids 
    ON 
     pool.id = rare_ids.id 
    CROSS JOIN 
    (SELECT @probability_divisor:=10) AS init 
) AS struct 
WHERE 
    random<probability 
ORDER BY 
    random 
LIMIT 3 

(проверьте скрипку here)

Объяснение на этом - это то, что вы определяете некоторый вероятностный делитель, а затем проверить, если случайно сгенерированное значение находится внутри интервала [0 .. 1/divisor] - это, конечно, зависит от того, что RAND() является порождающей значения из [0 .. 1]

в образце, 3 и 7 выбраны, чтобы быть «редкие люди иды» и эти люди будут появляться в наборе результатов с 1/10 нормальной PROBA Билити. Кроме того, я выбираю 3 строки с LIMIT, которые вы, скорее всего, захотите изменить.

Кроме того, LEFT JOIN был сделан только для указания места определения идентификаторов и других используемых вещей. Он может быть заменен IN, как:

SELECT 
    id, 
    name 
FROM 
    (SELECT 
    id, 
    name, 
    IF(id IN (3, 7), 1/@probability_divisor, 1) AS probability, 
    RAND() AS random 
    FROM 
    pool 
    CROSS JOIN 
    (SELECT @probability_divisor:=10) AS init 
) AS struct 
WHERE 
    random<probability 
ORDER BY 
    random 
LIMIT 3 

fiddle)

Пожалуйста, обратите внимание, что для больших наборов данных это будет работать очень медленно, но здравомыслящий количество строк она по-прежнему применяется.

+0

. Версия 2 отлично работает с тем, как я использую свое приложение, большое спасибо! – Curtis

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