SQL: запрос со сложными подзапросами - PullRequest
0 голосов
/ 03 июля 2011

У меня есть следующие таблицы в базе данных моей игры:

rankedUp (image_id, user_id, created_at)
globalRank (image_id, rank )
matchups (user_id, image_id1, image_id2)

Всем image_ids в таблице globalRank присвоен ранг с плавающей точкой от 0 до 1

Предполагается, что у меня есть текущийвошел в пользовательское значение "user_id", я ищу запрос, который вернет пару идентификаторов изображений (imageid1, imageid2), так что:

  1. imageid1 имеет более низкий ранг, чем imageid2, но такжеследующий наивысший ранг меньше, чем у imageid2
  2. таблицы соответствия нетили, если это так, столбец createat старше X часов

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

SELECT lowerImages.image_id AS lower_image, higherImages.image_id AS higher_image
FROM global_rank AS lowerImages, global_rank AS higherImages
WHERE lowerImages.rank < higherImages.rank
AND lowerImages.image_id = ( 
    SELECT image_id
    FROM (
        SELECT image_id
        FROM global_rank
        WHERE rank < higherImages.rank
        ORDER BY rank DESC 
        LIMIT 1 , 1
        ) AS tmp 
    ) 

, но оно не работает, потому что я не могу 't упоминание в подзапросе.*

Теперь у меня есть этот запрос, но я неТеперь об эффективности, и мне нужно проверить ее на правильность:

SELECT lowerImages.image_id AS lower_image,
       max(higherImages.image_id) AS higher_image
FROM global_rank AS lowerImages, global_rank AS higherImages
WHERE  lowerImages.rank  <  higherImages.rank

AND 1  NOT IN (select 1 from ranked_up where
    lowerImages.image_id = ranked_up.image_id
    AND ranked_up.user_id = $user_id
    AND ranked_up.created_at > DATE_SUB(NOW(), INTERVAL 1 DAY))

AND 1 NOT IN (
    SELECT 1 from matchups where user_id = $userId 
            AND lower_image_id = lowerImages.image_id 
            AND higher_image_id = higherImages.image_id
            UNION
            SELECT 1 from matchups where user_id = $user_id
            AND lower_image_id = higherImages.image_id 
            AND higher_image_id = lowerImages.image_id
)
GROUP BY 1

все операторы "not in", которые я использую, проиндексированы, поэтому они должны работать быстро.У меня проблема с эффективностью - группировка и выбор таблиц global_rank


Этот вопрос является ревизией Довольно сложный SQL-запрос , на который больше не нужно отвечать.

Ответы [ 2 ]

1 голос
/ 03 июля 2011

Это должно сработать:

SELECT lowerImages.*, higherImages.* 
FROM globalrank AS lowerImages, globalrank AS higherImages
WHERE lowerImages.rank < higherImages.rank
AND lowerImages.image_id = ( 
    SELECT image_id
    FROM (
        SELECT image_id
        FROM globalrank
        WHERE rank < higherImages.rank
        ORDER BY rank DESC 
        LIMIT 1,1
        ) AS tmp 
    ) 
AND NOT EXISTS (
    SELECT * FROM matchups 
    WHERE user_id = $user_id 
    AND ((image_id1 = lowerImages.image_id AND image_id2 = higherImages.image_id)
        OR (image_id2 = lowerImages.image_id AND image_id1 = higherImages.image_id))
)
AND higherImages.image_id NOT IN (
    SELECT image_id FROM rankedup 
    WHERE created_at < DATE_ADD(NOW(), INTERVAL 1 DAY)
    AND USER_ID <> $user_id
)
ORDER BY higherImages.rank

Я предполагаю, что PK матчей и ранжирования включают все столбцы в этих таблицах.Это позволило бы вторым 2 подзапросам использовать индексы PK.Возможно, вы захотите, чтобы упорядоченный индекс на globalrank.rank ускорил первый подзапрос.

1 голос
/ 03 июля 2011
select
(
select image_id, rank from
rankedup inner join globalRank 
on rankedup.image_id = globalRank .image_id
where user_id = XXX 
limit 1, 1
) as highest,
(
select image_id, rank from
rankedup inner join globalRank 
on rankedup.image_id = globalRank .image_id
where user_id = XXX 
limit 2, 1
) as secondhighest

Я обычно использую SQL Server, но я думаю, что это перевод для mysql:)

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