оптимизация mysql: выберите ранее не выбранную случайную пару различных значений из столбца уникальных значений - PullRequest
2 голосов
/ 24 ноября 2011

Каков был бы наиболее эффективный способ выбора ранее не выбранной пары различных случайных значений из столбца уникальных (не повторяющихся) значений?

Мой текущий подход заключается в том, чтобы сохранить каждую пару уже связанных значенийв отдельной таблице "mytable_associations"):

SELECT * FROM
(
 SELECT id,count(*) AS associations_count FROM mytable 
 INNER JOIN mytable_associations 
 WHERE (myvalue=myvalue1 OR myvalue=myvalue2) 
 GROUP BY myvalue 
 HAVING associations_count<(SELECT count(*) FROM mytable)-1
 ORDER BY rand() limit 1
) mytable1 
LEFT JOIN 
(SELECT myvalue AS myvalue2 FROM mytable) mytable2
ON mytable1.myvalue1<>mytable2.myvalue2
WHERE
(
 SELECT myvalue1 FROM mytable_associations 
 WHERE
 myvalue1=mytable1.myvalue1 AND myvalue2=mytable2.myvalue2
 OR
 myvalue1=mytable2.myvalue2 AND myvalue2=mytable1.myvalue1
) IS NULL;

(а затем, конечно, обновить mytable_associations с помощью этой новой ассоциации)

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

(Извините за плохой отступ в коде, я действительно не знаю, как делать отступы для команд mysql).

Вы можете мне помочь?

(PS ЭтоМой первый вопрос, который когда-либо был здесь опубликован: Конечно, я делаю много вещей неправильно, и я бы понял последующее пламя, но, пожалуйста, не обращайте на меня слишком много внимания;))

1 Ответ

2 голосов
/ 24 ноября 2011

Любое решение с участием order by rand() будет неэффективным. Для альтернатив см .:

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

$c1 = SELECT COUNT(DISTINCT myvalue) FROM mytable
$c2 = SELECT COUNT(*) FROM mytable_associations

$offset = ROUND( RAND() * ($c1 * ($c1-1) - $c2) )

SELECT v.* FROM (
  SELECT LEAST(m1.myvalue,my2.myvalue) AS myvalue1,
    GREATEST(m1.myvalue,my2.myvalue) AS myvalue2
  FROM (SELECT DISTINCT myvalue FROM mytable) AS m1 
  INNER JOIN (SELECT DISTINCT myvalue FROM mytable) AS m2
    ON m1.myvalue <> m2.myvalue
) AS v
LEFT OUTER JOIN mytable_associations AS a USING (myvalue1,myvalue2)
WHERE a.myvalue1 IS NULL
LIMIT 1 OFFSET $offset

Убедившись, что myvalue1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...