sql >> Database teknologi >  >> RDS >> PostgreSQL

Sådan finder du varer med *alle* matchende kategorier

ActiveRecord

For ActiveRecord kan du indsætte en metode som denne i din Item-klasse:

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
 

Så kan du filtrere dine forespørgsler som sådan:

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

Du kan også bruge scopes for at gøre det lidt mere venligt:

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])

Begge vil producere denne SQL

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)
 

Du behøver teknisk set ikke distinct del af den underforespørgsel, men jeg er ikke sikker på, om med eller uden ville være bedre for ydeevnen.

SQL

Der er et par tilgange i rå SQL

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
)
 

Det vil fungere i SQL Server - syntaksen kan være lidt anderledes i Postgres. Eller

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. få rå decimalværdi fra mysqldb-forespørgsel

  2. Kan ikke tilføje felt...rækkestørrelse...større end den maksimalt tilladte størrelse

  3. Sådan viser du tabeller i den aktuelle database ved hjælp af PostgreSQL

  4. Hvordan kan jeg lægge to forespørgsler i en mysql_query?