所以想象一下,你有一个表Products (ID int, Name nvarchar(200))
,还有另外两个表,ProductsCategories (ProductID int, CategoryID int)
和InvoiceProducts (InvoiceID int, ProductID int)
。
我需要编写一个查询来生成一组与给定的一组发票 ID 和类别 ID 匹配的产品,以便产品列表匹配所有指定的类别和所有指定的发票,而无需回退到动态 SQL。想象一下,我需要查找属于 1 类和 2 类以及发票 3 和 4 的产品列表。
首先,我编写了一个存储过程,它接受类别 ID 和发票 ID 作为字符串,并将它们解析为表格:
CREATE PROCEDURE dbo.SearchProducts (@categories varchar(max), @invoices varchar(max))
AS BEGIN
with catids as (select cast([value] as int) from dbo.split(@categories, ' ')),
invoiceids as (select cast([value] as int) from dbo.split(@invoices, ' '))
select * from products --- insert awesomeness here
END
我提出的不同解决方案看起来很糟糕,而且性能更差。我发现的最好的事情是生成一个由所有条件的左连接组成的视图,但这似乎非常昂贵,并且不能解决匹配所有指定的不同键的问题。
更新: 这是我编写的一个示例查询,它产生了预期的结果。我错过了任何优化机会吗?像忍者的神奇独角兽矩阵运算?
with catids as (select distinct cast([value] as int) [value] from dbo.split(@categories, ' ')),
invoiceids as (select distinct cast([value] as int) [value] from dbo.split(@invoices, ' '))
select pc.ProductID from ProductsCategories pc (nolock)
inner join catids c on c.value = pc.CategoryID
group by pc.ProductID
having COUNT(*) = (select COUNT(*) from catids)
intersect
select ip.ProductID from InvoiceProducts ip (nolock)
inner join invoiceids i on i.value = ip.InvoiceID
group by ip.ProductID
having COUNT(*) = (select COUNT(*) from invoiceids)