如何找到必须有N>的行? 1个关联作为避免N + 1个查询的条件

时间:2012-06-13 09:50:12

标签: mysql polymorphic-associations

鉴于下表:

id  category_id categorizable_id  categorizable_type
66  22          67                Image
72  22          75                Image
74  15          71                Image
104 15          67                Image
126 15          113               Image

现在我想通过左连接选择那些“图像”,其category_ids为22 15 我的sql目前看起来像这样:

SELECT images.id FROM images 
  LEFT OUTER JOIN category_links 
    ON images.id = category_links.categorizable_id AND category_links.categorizable_type = 'Image' 
    where 
      category_links.category_id = "22" AND
      ( 
        select count(*) from category_links 
          where category_links.categorizable_id = images.id AND 
          category_links.categorizable_type = 'Image' AND 
          category_links.category_id = "15"
      )

如何在不需要子查询的情况下重写它?

3 个答案:

答案 0 :(得分:2)

如果没有子查询,您将无法有效地执行此操作,但情况仍有改进的空间:

SELECT * FROM
    (SELECT images.id, COUNT(l.categorizable_id) AS occurrences
     FROM images i
     LEFT OUTER JOIN category_links l
     ON i.id = l.categorizable_id AND l.categorizable_type = 'Image'
     WHERE l.category_id IN (15, 22)
     GROUP BY l.categorizable_id) temp
WHERE occurrences = 2;

这里的主要优点是配置此查询非常简单:您可以使用IN(...)指定要搜索的类别,以及这些类别中有多少必须与occurrences = N测试匹配。< / p>

上述查询将返回两个类别中的所有图像;如果occurrences >= 1它将返回任一类别或两者中的图像;等

如果您使用HAVING代替WHERE进行occurrences检查,则可能会丢失子查询,但这通常不是一个好主意,因为实质上它会过滤子查询的结果(如上所述)逐行,因此性能受损。

答案 1 :(得分:1)

如果您需要不同的图像ID,则可以使用distinct。

SELECT distinct images.id, 
COUNT(links.categorizable_id) AS occurrences
FROM images i
LEFT OUTER JOIN category_links links
ON i.id = links.categorizable_id AND links.categorizable_type = 'Image'
WHERE links.category_id IN (15, 22)
GROUP BY links.categorizable_id) temp
Having Count(links.categorizable_id) >= 2;

答案 2 :(得分:1)

SELECT
    a.id
FROM
    images a
INNER JOIN
    category_links b ON a.id = b.categorizable_id
WHERE
    b.categorizable_type = 'Image'
    AND 
    b.category_id IN (22, 15)
GROUP BY
    a.id
HAVING
    COUNT(*) = 2