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 が 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"
      )

サブクエリの必要性をなくすために、これをどのように書き直すことができますか?

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
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 に答える
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 に答える