想象一下,您有一个表Products (ID int, Name nvarchar(200))
,以及另外两个表,ProductsCategories (ProductID int, CategoryID int)
和InvoiceProducts (InvoiceID int, ProductID int)
。复杂的SQL查询 - 查找与多个不同外键匹配的项目
我需要编写一个查询来生成一组匹配给定的发票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)
您是否尝试过创建临时表,填充它,然后执行查询? – BobbyShaftoe 2010-10-25 22:29:37
这看起来像一个非常性感的解决方案给我。你应该添加这个答案。 – 2010-10-27 14:45:39
@mootinator:是的,这也发生在我身上。当临时表开始看起来很性感时,我知道是时候出去看看一些真正的女孩。 – Quassnoi 2010-10-27 15:00:56