关于复杂sql语句的建议

时间:2011-06-13 17:27:45

标签: mysql

SELECT `v`.*
  , GROUP_CONCAT(DISTINCT(`gg`.genre_id)) AS `genre_ids`
  , GROUP_CONCAT(DISTINCT(`gg`.genre_ru)) AS `genres`
  , GROUP_CONCAT(DISTINCT(`tg`.tag_id)) AS `tags_ids`
  , GROUP_CONCAT(DISTINCT(`tg`.name)) AS `tags`
FROM `video` AS `v`
LEFT JOIN `video_categories` AS `gc` ON gc.video_id = v.video_id
LEFT JOIN `video_genres` AS `gg` ON gg.genre_id = gc.genre_id
LEFT JOIN `tags_relations` AS `tr` ON tr.department=18 AND tr.parent_id = v.video_id
LEFT JOIN `tags` AS `tg` ON tg.tag_id = tr.tag_id
WHERE (v.video_id IN (
  SELECT gc2.video_id
  FROM video_categories gc2
  WHERE gc2.genre_id IN(44)
  GROUP BY gc2.video_id
  HAVING COUNT(gc2.video_id)=1)) 
AND (v.video_id IN (
  SELECT gc2.parent_id
  FROM tags_relations gc2
  WHERE gc2.tag_id IN(14) AND gc2.department=18
  GROUP BY gc2.parent_id
  HAVING COUNT(gc2.parent_id)=1))
GROUP BY `v`.`video_id`
ORDER BY `v`.`video_id` DESC

查询需要0.4s~才能运行。这是因为WHERE语句中的子查询:

v.video_id IN (
    SELECT gc2.parent_id
    FROM tags_relations gc2
    WHERE gc2.tag_id IN(14) AND gc2.department=18
    GROUP BY gc2.parent_id
    HAVING COUNT(gc2.parent_id)=1
)

没有它,它运行0.07s~

也许尝试使用高级连接? 害羞

谢谢;)

2 个答案:

答案 0 :(得分:1)

在MySQL中,永远不要使用WHERE in (SELECT ...,这是非常慢的。

改为使用联接:

SELECT `v`.*
  , GROUP_CONCAT(DISTINCT(`gg`.genre_id)) AS `genre_ids`
  , GROUP_CONCAT(DISTINCT(`gg`.genre_ru)) AS `genres`
  , GROUP_CONCAT(DISTINCT(`tg`.tag_id)) AS `tags_ids`
  , GROUP_CONCAT(DISTINCT(`tg`.name)) AS `tags`
FROM video AS v
INNER JOIN video_categories AS gc ON gc.video_id = v.video_id 
  AND gc2.genre_id = '44'
LEFT JOIN video_genres AS gg ON gg.genre_id = gc.genre_id
LEFT JOIN tags_relations AS tr ON tr.department=18 AND tr.parent_id = v.video_id
LEFT JOIN tags AS tg ON tg.tag_id = tr.tag_id
INNER JOIN tags_relations tr2 ON (tr2.parent_id = v.video_id 
  AND tr2.tag_id = 14 AND tr2.department=18
GROUP BY `v`.`video_id`
ORDER BY `v`.`video_id` DESC

答案 1 :(得分:0)

SELECT `v`.*
  , GROUP_CONCAT(DISTINCT(`gg`.genre_id)) AS `genre_ids`
  , GROUP_CONCAT(DISTINCT(`gg`.genre_ru)) AS `genres`
  , GROUP_CONCAT(DISTINCT(`tg`.tag_id)) AS `tags_ids`
  , GROUP_CONCAT(DISTINCT(`tg`.name)) AS `tags`
FROM `video` AS `v`
LEFT JOIN `video_categories` AS `gc` ON gc.video_id = v.video_id
LEFT JOIN `video_genres` AS `gg` ON gg.genre_id = gc.genre_id
LEFT JOIN `tags_relations` AS `tr` ON tr.department=18 AND tr.parent_id = v.video_id
LEFT JOIN `tags` AS `tg` ON tg.tag_id = tr.tag_id
JOIN (
  SELECT gc2.video_id
  FROM video_categories gc2
  WHERE gc2.genre_id IN(44)
  GROUP BY gc2.video_id
  HAVING COUNT(gc2.video_id)=1
  ) vc ON v.video_id = vc.video_id
JOIN (
  SELECT gc2.parent_id
  FROM tags_relations gc2
  WHERE gc2.tag_id IN(14) AND gc2.department=18
  GROUP BY gc2.parent_id
  HAVING COUNT(gc2.parent_id)=1
  ) tr ON v.video_id = tr.parent_id
GROUP BY `v`.`video_id`
ORDER BY `v`.`video_id` DESC

编辑:

我仔细查看了您的查询,并认为可以将其简化为以下内容:

SELECT `v1`.*
  , GROUP_CONCAT(DISTINCT(`gg`.genre_id)) AS `genre_ids`
  , GROUP_CONCAT(DISTINCT(`gg`.genre_ru)) AS `genres`
  , GROUP_CONCAT(DISTINCT(`tg`.tag_id)) AS `tags_ids`
  , GROUP_CONCAT(DISTINCT(`tg`.name)) AS `tags`
FROM (
SELECT v.*
FROM `video` AS `v`
LEFT JOIN `video_categories` AS `gc` ON gc.video_id = v.video_id
LEFT JOIN `tags_relations` AS `tr` ON tr.parent_id = v.video_id
WHERE gc.genre_id IN(44)
  AND tr.tag_id IN(14)
  AND tr.department=18
GROUP BY `v`.`video_id`
HAVING COUNT(*) = 1
) v1
LEFT JOIN `video_genres` AS `gg` ON gg.genre_id = gc.genre_id
LEFT JOIN `tags` AS `tg` ON tg.tag_id = tr.tag_id
GROUP BY v1.video_id
ORDER BY v1.video_id DESC