SQL SELECT multiple conditions from many to many relationships

I am struggling to find an elegant solution to this problem. I have 5 tables and their relationship is described in the image. enter image description here

A page can contain multiple products, and each product can have many ProductRates. A page with a specific product can have a lot of bids. To work around many of the problems, there is a PageToProductToRate table.

Users want to request multiple conditions, where the choice can be a combination of any of them:

  • Product1 + Rate1 + rate attribute1
  • Product1 + Rate1 + rate attribute2
  • Product1 + Rate2 + rate attribute2
  • Product2 + Rate3 + rate attribute1, etc.

This is an example of data and WHERE clause and expected results: enter image description here

And further: enter image description here

The query that works for me is using INTERSECT to get correct results. I tried UNION but didn't get all the results.

SELECT DISTINCT P.[PageID]
FROM [Page] P
  join PageToProduct p2p on p2p.[PageID] = P.[PageID] 
  join Product pr on p2p.[Product] = pr.[Product] 
  join PageToProductToRate p2p2r on p2p2r.[PageToProductID] = p2p.[PageToProductID] 
  join ProductRates r on r.[ProductRatesID] = p2p2r.[ProductRatesID] 
  WHERE (PR.[Product] = 'ALMOND' AND R.CommissionType = 'PREMIUM' AND R.Rate = 0.25) 
INTERSECT
SELECT DISTINCT P.[PageID]
FROM [Page] P
  join PageToProduct p2p on p2p.[PageID] = P.[PageID] 
  join Product pr on p2p.[Product] = pr.[Product] 
  join PageToProductToRate p2p2r on p2p2r.[PageToProductID] = p2p.[PageToProductID] 
  join ProductRates r on r.[ProductRatesID] = p2p2r.[ProductRatesID] 
  WHERE (PR.[Product] = 'WALNUT' AND R.CommissionType = 'SERVICE FEE' AND R.Rate = 1.25)
INTERSECT
SELECT DISTINCT P.[PageID]
FROM [Page] P
  join PageToProduct p2p on p2p.[PageID] = P.[PageID] 
  join Product pr on p2p.[Product] = pr.[Product] 
  join PageToProductToRate p2p2r on p2p2r.[PageToProductID] = p2p.[PageToProductID] 
  join ProductRates r on r.[ProductRatesID] = p2p2r.[ProductRatesID] 
  WHERE (PR.[Product] = 'HAZELNUT' AND R.CommissionType = 'EXCESS' AND R.Rate = 1.68)

      

Is there a better way to solve this problem? I could have over a dozen of these conditions and a query with all the joins could get out of hand.

+3
sql sql-server sql-server-2008


source to share


3 answers


SELECT p2p.PageID
FROM
    PageToProduct as p2p
    inner join Product as pr
        on p2p.Product = pr.Product
    inner join PageToProductToRate as p2p2r
        on p2p2r.PageToProductID = p2p.PageToProductID
    inner join ProductRates as r
        on r.ProductRatesID = p2p2r.ProductRatesID 
WHERE
          (pr.Product = 'ALMOND' AND r.CommissionType = 'PREMIUM' AND r.Rate = 0.25) 
      OR  (pr.Product = 'WALNUT' AND r.CommissionType = 'SERVICE FEE' AND r.Rate = 1.25)
      OR  (pr.Product = 'HAZELNUT' AND r.CommissionType = 'EXCESS' AND r.Rate = 1.68)
GROUP BY p2p.PageID
HAVING COUNT(*) = 3; /* requires all three are present, as long as no rows are duplicate */

      



+1


source to share


My best guess.

WITH products AS 
(
    SELECT  [Product],
            [ProductRatesID]
    FROM    Product p
            JOIN ProductRates pr ON p.[Product] = pr.[Product]
    WHERE   (p.[Product] = 'ALMOND' AND pr.CommissionType = 'PREMIUM' AND pr.Rate = 0.25)
            OR (p.[Product] = 'WALNUT' AND pr.CommissionType = 'SERVICE FEE' AND pr.Rate = 1.25)
            OR (p.[Product] = 'HAZELNUT' AND pr.CommissionType = 'EXCESS' AND pr.Rate = 1.68)
)
SELECT  P.[PageID]
FROM    [Page] P
        JOIN (
            SELECT  p2p.[PageID], COUNT(*) as ProductCount
            FROM    products pr
                    JOIN PageToProduct p2p ON p2p.[Product] = pr.[Product]
                    JOIN PageToProductToRate p2p2r on p2p2r.[PageToProductID] = p2p.[PageToProductID] 
            WHERE   p2p2r.[ProductRatesID] = pr.[ProductRatesID]
            GROUP BY p2p.[PageID]
        ) sq ON sq.[PageID] = p.[PageID]
WHERE   sq.ProductCount = @ProductFilterCount

      



You need to figure out how you want to process @ProductFilterCount

. This can be either the number of number filters you use, or the number of products that actually match those filters.

SQL Fiddle

+1


source to share


I'm not sure what you are asking .. but if you want pages that have product choices then this might work, you have to test yourself though

edit- changed to AND because he wants all conditions to be met

SELECT DISTINCT P.[PageID]
FROM [Page] P
  join PageToProduct p2p on p2p.[PageID] = P.[PageID] 
  join Product pr on p2p.[Product] = pr.[Product] 
  join PageToProductToRate p2p2r on p2p2r.[PageToProductID] = p2p.[PageToProductID] 
  join ProductRates r on r.[ProductRatesID] = p2p2r.[ProductRatesID] 
  WHERE (PR.[Product] = 'ALMOND' AND R.CommissionType = 'PREMIUM' AND R.Rate = 0.25) 
  AND (PR.[Product] = 'WALNUT' AND R.CommissionType = 'SERVICE FEE' AND R.Rate = 1.25)
  AND (PR.[Product] = 'HAZELNUT' AND R.CommissionType = 'EXCESS' AND R.Rate = 1.68)

      

0


source to share







All Articles
Loading...
X
Show
Funny
Dev
Pics