0

给定下表:

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 是 2215 我的 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"
      )

如何重写以消除对子查询的需要?

4

3 回答 3

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测试匹配。

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

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

于 2012-06-13T10:04:47.257 回答
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;
于 2012-06-13T10:07:12.973 回答
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
于 2012-06-13T10:45:00.120 回答