鉴于下表:
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"
)
如何在不需要子查询的情况下重写它?
答案 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