PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Cara menemukan item dengan *semua* kategori yang cocok

ActiveRecord

Untuk ActiveRecord, Anda bisa meletakkan metode seperti ini di kelas Item Anda:

def self.with_all_categories(category_ids)
  select(:id).distinct.
    joins(:categories).
    where('categories.id' => category_ids).
    group(:id).
    having('count(categories.id) = ?', category_ids.length)
end

Kemudian Anda dapat memfilter kueri Anda seperti ini:

category_ids = [1,2,3]
Item.where(id: Item.with_all_categories(category_ids))

Anda juga dapat menggunakan cakupan untuk membuatnya sedikit lebih ramah:

class Item
  scope :with_all_categories, ->(category_ids) { where(id: Item.ids_with_all_categories(category_ids)) }

  def self.ids_with_all_categories(category_ids)
    select(:id).distinct.
      joins(:categories).
      where('categories.id' => category_ids).
      group(:id).
      having('count(categories.id) = ?', category_ids.length)
  end
end

Item.with_all_categories([1,2,3])

Keduanya akan menghasilkan SQL ini

SELECT "items".*
FROM "items"
WHERE "items"."id" IN
  (SELECT DISTINCT "items"."id"
   FROM "items"
   INNER JOIN "categories_items" ON "categories_items"."item_id" = "items"."id"
   INNER JOIN "categories" ON "categories"."id" = "categories_items"."category_id"
   WHERE "categories"."id" IN (1, 2, 3)
   GROUP BY "items"."id" 
   HAVING count(categories.id) = 3)

Secara teknis Anda tidak memerlukan distinct bagian dari subkueri itu, tetapi saya tidak yakin apakah dengan atau tanpa itu kinerjanya akan lebih baik.

SQL

Ada beberapa pendekatan dalam SQL mentah

SELECT *
FROM items
WHERE items.id IN (
  SELECT item_id
  FROM categories_items
  WHERE category_id IN (1,2,3)
  GROUP BY item_id
  HAVING COUNT(category_id) = 3
)

Itu akan berfungsi di SQL Server - sintaksnya mungkin sedikit berbeda di Postgres. Atau

SELECT *
FROM items
WHERE items.id IN (SELECT item_id FROM categories_items WHERE category_id = 1)
  AND items.id IN (SELECT item_id FROM categories_items WHERE category_id = 2)
  AND items.id IN (SELECT item_id FROM categories_items WHERE category_id = 3)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara memetakan kolom stempel waktu ke tipe JPA?

  2. PostgreSQL regexp_replace dengan ekspresi yang cocok

  3. perbarui data xml menggunakan kueri sql di postgresql

  4. Postgres:mengonversi satu baris menjadi beberapa baris (unpivot)

  5. Peningkatan otomatis PostgreSQL meningkat pada setiap pembaruan