Одной из проблем является передача массива или списка выбранных категорий на сервер. Эланд Соммарског широко освещал эту тему в серии статей Массивы и списки в SQL Server . Передача списка в виде строки, разделенной запятыми, и создание временной таблицы - один из вариантов. Существуют альтернативы, такие как использование XML или Table-Valued-Parameter (в SQL Server 2008) или использование таблицы @variable вместо таблицы #temp. Плюсы и минусы каждого раскрыты в статьях, на которые я ссылаюсь.
Теперь о том, как получить продукты. Перво-наперво: если выбраны все категории, тогда используйте другой запрос, который просто извлекает все продукты без каких-либо категорий. Это сэкономит много производительности, и, учитывая, что все пользователи, вероятно, сначала увидят страницу без выбранной категории, экономия может быть значительной.
Когда категории выбраны , тогда создание запроса, объединяющего продукты, категории и выбранные категории, довольно просто. Настройка и масштабирование - это отдельная тема, и она полностью зависит от вашей схемы данных и фактического шаблона выбранных категорий. Наивный подход такой:
select ...
from Products p
where p.IsEnabled = 1
and exists (
select 1
from ProductCategories pc
join #selectedCategories sc on sc.CategoryID = pc.CategoryID
where pc.ProductID = p.ProductID);
У ProductsCategoriestable индекс должен быть (ProductID, CategoryID)
, а другой - (CategoryID, ProductID)
(один из них кластеризованный, другой - NC). Это верно для каждого решения между прочим. Этот запрос будет работать, если всегда выбраны большинство категорий, а результат в любом случае содержит большинство продуктов. Но если список выбранных категорий ограничен, то лучше избегать сканирования в потенциально большой таблице «Продукты» и начинать с выбранных категорий:
with distinctProducts as (
select distinct pc.ProductID
from ProductCategories pc
join #selectedCategories sc on pc.CategoryID = sc.CategoryID)
select p.*
from Products p
join distinctProducts dc on p.ProductID = dc.ProductID;
Опять же, лучшее решение во многом зависит от формы ваших данных. Например, если у вас есть очень искаженная категория (одна категория покрывает 99% продуктов), тогда наилучшее решение должно учитывать этот перекос.