MySQL中的INTERSECT替换

时间:2015-10-29 10:15:50

标签: mysql sql

我正在努力使这个查询与MySQL兼容:

SELECT stories.*,
  (SELECT id FROM models WHERE model_user_id = stories.user_id AND user_id = ? LIMIT 1) 
  AS c_model_id
FROM stories
WHERE
  c_model_id IS NOT NULL
  AND
  EXISTS (
   SELECT tag_id FROM stories_tags WHERE story_id = stories.id
   INTERSECT
   SELECT tag_id FROM models_tags WHERE model_id = c_model_id
  )

我根据this question尝试了以下内容。

SELECT 
  stories.*,
  (SELECT id FROM models WHERE model_user_id = stories.user_id AND user_id = ? LIMIT 1)
  AS c_model_id
FROM stories
WHERE
  c_model_id IS NOT NULL
  AND
  EXISTS (SELECT t1.tag_id FROM (
    SELECT tag_id FROM stories_tags WHERE story_id = stories.id -- Here
    UNION ALL
    SELECT tag_id FROM models_tags WHERE model_id = c_model_id
  ) AS t1 GROUP BY tag_id HAVING COUNT(*) >= 2)

但是我遇到了一个新问题:我无法从最深的子查询中访问stories表:Unknown column 'stories.id' in 'where clause'

我无法找到这个问题的任何解决方案,但可能有一个,我只是没有看到它。

修改

我找到了一个与MySQL兼容的查询:

SELECT stories.*
FROM stories
INNER JOIN models ON model_user_id = stories.user_id AND models.user_id = ?
WHERE EXISTS
(
 SELECT stories_tags.tag_id
 FROM stories_tags
 LEFT JOIN models_tags
 ON models_tags.tag_id = stories_tags.tag_id
 WHERE models_tags.model_id = models.id AND story_id = stories.id
)

我认为它等于第一个查询。有人可以帮我核实一下吗?

1 个答案:

答案 0 :(得分:0)

您的INTERSECT说:只向我提供两个集中存在匹配标记的记录。所以你也可以通过标签加入表格然后搜索:

SELECT 
  stories.*,
  (SELECT id FROM models WHERE model_user_id = stories.user_id AND user_id = ? LIMIT 1) 
    AS c_model_id
FROM stories
WHERE EXISTS
(
  SELECT * 
  FROM stories_tags st
  JOIN models_tags mt ON mt.tag_id = st.tag_id
  WHERE st.story_id = stories.id
  AND mt.model_id = stories.c_model_id
);

我顺便删除了WHERE c_model_id IS NOT NULL,为了匹配models_tags中的记录,无论如何这必须是真的。

作为两个你自己的建议:你的外连接(LEFT JOIN)根本不是外连接,因为在你的WHERE子句中你说你只想要匹配(WHERE models_tags.model_id = models.id),从而将连接转换为内部联接。这看起来正是我提出的:-)但是你也改变了你的SELECT子句。现在,您可以内部加入models表,而不是选择用户模型条目(如果存在)。因此,如果记录不存在,则现在不会获得任何数据。您可以通过外部加入models代替:LEFT JOIN models来解决此问题。如果有多个匹配,您现在将获得重复结果。但是,是否有可能不能从子查询中获得一个记录,我不知道。也许它不是,那么你的查询就可以了。