给出下表:
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_id 为 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"
)
如何重写它以消除对子查询的需要?
最佳答案
如果没有子查询,您将无法有效地执行此操作,但情况还有改进的余地:
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
测试。
上述查询将因此返回属于两个类别的所有图像;如果 occurrences >= 1
它将返回任一类别或两者的图像;等
如果您使用 HAVING
而不是 WHERE
进行 occurrences
检查,您可能会丢失子查询,但这通常不是一个好主意,因为本质上,它逐行过滤子查询(如上所述)的结果,因此性能受到影响。
关于mysql - 我如何找到必须具有 N > 1 关联的行作为避免 N+1 查询的条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11012342/