复杂的SQL查询 – 查找匹配多个不同外键的项目

前端之家收集整理的这篇文章主要介绍了复杂的SQL查询 – 查找匹配多个不同外键的项目前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
因此,假设您有一个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作为字符串接受,并将它们解析为表格:

  1. CREATE PROCEDURE dbo.SearchProducts (@categories varchar(max),@invoices varchar(max))
  2. AS BEGIN
  3. with catids as (select cast([value] as int) from dbo.split(@categories,' ')),invoiceids as (select cast([value] as int) from dbo.split(@invoices,' '))
  4. select * from products --- insert awesomeness here
  5. END

我提出的不同解决方案看起来很糟糕,而且表现更差.我发现的最好的事情是生成一个由所有条件的左连接组成的视图,但这似乎非常昂贵,并没有解决匹配指定的所有不同键的问题.

更新:这是我编写的一个示例查询,可以产生预期的结果.我错过了任何优化机会吗?像忍者的魔法独角兽矩阵操作一样?

  1. 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,' '))
  2.  
  3. select pc.ProductID from ProductsCategories pc (nolock)
  4. inner join catids c on c.value = pc.CategoryID
  5. group by pc.ProductID
  6. having COUNT(*) = (select COUNT(*) from catids)
  7. intersect
  8. select ip.ProductID from InvoiceProducts ip (nolock)
  9. inner join invoiceids i on i.value = ip.InvoiceID
  10. group by ip.ProductID
  11. having COUNT(*) = (select COUNT(*) from invoiceids)

解决方法

如果您在(ProductID,CategoryID)和(ProductID,InvoiceID)上都有唯一索引:
  1. SELECT ProductID
  2. FROM (
  3. SELECT ProductID
  4. FROM ProductInvoice
  5. WHERE InvoiceID IN (1,2)
  6. UNION ALL
  7. SELECT ProductID
  8. FROM ProductCategory pc
  9. WHERE CategoryID IN (3,4)
  10. ) q
  11. GROUP BY
  12. ProductID
  13. HAVING COUNT(*) = 4

或者,如果您的值以CSV字符串传递:

  1. WITH catids(value) AS
  2. (
  3. SELECT DISTINCT CAST([value] AS INT)
  4. FROM dbo.split(@categories,' '))
  5. ),(
  6. SELECT DISTINCT CAST([value] AS INT)
  7. FROM dbo.split(@invoices,' '))
  8. )
  9. SELECT ProductID
  10. FROM (
  11. SELECT ProductID
  12. FROM ProductInvoice
  13. WHERE InvoiceID IN
  14. (
  15. SELECT value
  16. FROM invoiceids
  17. )
  18. UNION ALL
  19. SELECT ProductID
  20. FROM ProductCategory pc
  21. WHERE CategoryID IN
  22. (
  23. SELECT value
  24. FROM catids
  25. )
  26. ) q
  27. GROUP BY
  28. ProductID
  29. HAVING COUNT(*) =
  30. (
  31. SELECT COUNT(*)
  32. FROM catids
  33. ) +
  34. (
  35. SELECT COUNT(*)
  36. FROM invoiceids
  37. )

请注意,在sql Server 2008中,您可以将表值参数传递到存储过程中.

猜你在找的MsSQL相关文章