【问题标题】:Reuse result of a correlated subquery重用相关子查询的结果
【发布时间】:2019-07-22 21:30:13
【问题描述】:

我有一个表media_tags,其中包含两列将媒体链接到用户定义的标签。我想做一些查询,选择标签上条件复杂的媒体。我当前的解决方案是多次使用相同的相关子查询。

多个 SO 答案已将我指向 CTE,但据我了解,这些只能用于替换不相关的子查询。

SELECT outer.media_id
FROM media_tags AS outer
WHERE 1 IN (SELECT tag_id FROM media_tags AS inner WHERE outer.media_id = inner.media_id)
AND 2 NOT IN (SELECT tag_id FROM media_tags AS inner WHERE outer.media_id = inner.media_id)
AND (3 IN (SELECT tag_id FROM media_tags AS inner WHERE outer.media_id = inner.media_id)
OR 4 IN (SELECT tag_id FROM media_tags AS inner WHERE outer.media_id = inner.media_id));

【问题讨论】:

    标签: sql sqlite query-optimization correlated-subquery


    【解决方案1】:

    您可以进行自联接,GROUP BY media_id 并在HAVING 子句中设置条件:

    SELECT outer.media_id
    FROM media_tags AS outer INNER JOIN media_tags AS inner
    ON outer.media_id = inner.media_id
    GROUP BY outer.media_id
    HAVING 
      SUM(inner.tag_id = 1) > 0
      AND
      SUM(inner.tag_id = 2) = 0
      AND
      SUM(inner.tag_id IN (3, 4)) > 0
    

    或者更简单,如果没有自连接检查这是否也有效:

    SELECT media_id
    FROM media_tags
    GROUP BY media_id
    HAVING 
      SUM(tag_id = 1) > 0
      AND
      SUM(tag_id = 2) = 0
      AND
      SUM(tag_id IN (3, 4)) > 0
    

    【讨论】:

      【解决方案2】:

      not exists怎么样?

      SELECT m2.media_id
      FROM media_tags mt
      WHERE NOT EXISTS (SELECT tag_id
                        FROM media_tags mt2
                        WHERE mt2.media_id = mt.media_id AND
                              mt2.tag_id IN (1, 2, 3, 4)
                       );
      

      【讨论】:

      • 我没有看到将它用于复杂查询的方法,例如 tag_1 AND NOT tag_2 AND (tag_3 OR tag_4)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多