Consulta SQL complicada: búsqueda de elementos que coinciden con varias claves externas diferentes

Así que imagina que tienes una mesa deProducts (ID int, Name nvarchar(200))y otras dos mesas,ProductsCategories (ProductID int, CategoryID int) yInvoiceProducts (InvoiceID int, ProductID int).

Necesito escribir una consulta para producir un conjunto de productos que coincidan con un conjunto dado de identificadores de factura y de categoría, de modo que la lista de productos coincida con todas las categorías especificadas y todas las facturas especificadas, sin recurrir al SQL dinámico. Imagine que necesito encontrar una lista de productos que están en las categorías 1 y 2 y en las facturas 3 y 4.

Como principio, he escrito un procedimiento almacenado que acepta los identificadores de categoría y los identificadores de factura como cadenas, y los analiza en tablas:

 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

Las diferentes soluciones que se me ocurren se ven horribles y funcionan peor. Lo mejor que he encontrado es generar una vista compuesta por uniones izquierdas de todos los criterios, pero eso parece muy costoso y no resuelve el problema de hacer coincidir todas las diferentes claves especificadas.

Actualizar: Este es un ejemplo de consulta que escribí que produce los resultados esperados. ¿Me estoy perdiendo alguna oportunidad de optimización? ¿Como las operaciones mágicas de matriz de unicornio de ninjas?

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)   

Respuestas a la pregunta(4)

Su respuesta a la pregunta