PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да намерите елементи с *всички* съвпадащи категории

ActiveRecord

За ActiveRecord можете да поставите метод като този във вашия клас Item:

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

След това можете да филтрирате вашите заявки по следния начин:

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

Можете също така да използвате обхвати, за да го направите малко по-приятелски:

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

И двете ще създадат този 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)

Технически не се нуждаете от distinct част от тази подзаявка, но не съм сигурен дали със или без би било по-добре за производителността.

SQL

Има няколко подхода в необработения 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
)

Това ще работи в SQL Server - синтаксисът може да е малко по-различен в Postgres. Или

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. Грешка при изпълнение на командата psql в /docker-entrypoint-initdb.d/db_init.sh (psql:не можа да се свърже със сървъра:връзката е отказана)

  2. Приложението Spring Boot се забива на Hikari-Pool-1 - Стартиране...

  3. Задействане на Postgres за актуализиране на кеша на Java

  4. PostgreSQL:Експортиране на данни от SQL Server 2008 R2 към PostgreSQL 9.5

  5. psql клиентът вече може да бъде шах...