ActiveRecord
ActiveRecord के लिए, आप अपने आइटम वर्ग में इस तरह की एक विधि डाल सकते हैं:
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])
दोनों इस एसक्यूएल का निर्माण करेंगे
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
. की आवश्यकता नहीं है उस सबक्वेरी का हिस्सा, लेकिन मुझे यकीन नहीं है कि प्रदर्शन के लिए बेहतर होगा या नहीं।
एसक्यूएल
कच्चे एसक्यूएल में कुछ दृष्टिकोण हैं
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 सर्वर में काम करेगा - पोस्टग्रेज में सिंटैक्स थोड़ा अलग हो सकता है। या
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)