2015-06-12 4 views
3

Я изо всех сил стараюсь найти элегантное решение этой проблемы. У меня 5 таблиц, и их отношения описаны на изображении. enter image description hereSQL SELECT несколько условий для многих отношений

Страница может иметь несколько продуктов, и каждый продукт может иметь много ProductRates. Страница с конкретным продуктом может иметь много ставок. Чтобы обойти многие проблемы, существует таблица PageToProductToRate.

Пользователи хотят запроса на нескольких условиях, когда выбор может быть сочетание любого:

  • Product1 + rate1 + скорость attribute1
  • Product1 + rate1 + скорость attribute2
  • attribute2
  • Product1 + rate2 + скорость
  • Product2 + Rate3 + скорость attribute1 и т.д. ...

Это пример данных и где состояние и ожидаемые результаты: enter image description here

И еще: enter image description here

Запрос, который работает для меня использует INTERSECT, чтобы получить правильные результаты. Я попробовал UNION, но получил результаты, не соответствующие всем условиям.

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) 

Есть ли лучший способ решить эту проблему? Я мог бы иметь более дюжины этих условий, и запрос со всеми объединениями мог выйти из-под контроля.

+0

Вы пытаетесь выбрать страницы, которые не имеют выбранные продукты? – tshoemake

+0

Вы используете параметры для фильтрации данных? если так, то как они выглядят? – JamieD77

+0

Я думаю, вместо '() AND() AND()', вам нужно '() OR() OR()'. –

ответ

1
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

это было просто и эффективно, работал в каждом экземпляре, который я тестировал. – AidaM

0

Я не уверен, что вы спрашиваете .. но если вы хотите страницы, которые имеют выбор продукта, то это может работать, вы должны проверить себя, хотя

Edit- изменен и потому, что он хочет все условия выполнены

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) 
+1

Это недопустимый синтаксис. «EXISTS (« должен следовать SELECT ». –

1

Мое лучшее предположение.

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 

Вам нужно выяснить, как вы хотите, чтобы справиться с @ProductFilterCount. Это может быть либо счетчик числа фильтров, которые вы используете, или количество продуктов, которые на самом деле соответствуют этим фильтрам

SQL Fiddle

+0

Я не уверен, в чем проблема фильтра продукта, о котором вы говорите? Я все еще пытаюсь заставить это работать, оно возвращает результаты только в том случае, если у меня есть условие «WHERE». Почему у вас есть счетчик (*) в инструкции select? @ User1221684 – AidaM

+0

Посмотрите на созданный мной SQL-скрипт. – JamieD77