Функция SQL для поиска заказов с несовместимыми продуктами - PullRequest
0 голосов
/ 09 октября 2019

Проблема возникает из-за двух типов продуктов (скажем, летучих мышей и мячей) и двух диапазонов продуктов (например, бейсбол и крикет).

Я хочу получать заказы на крикетные биты и бейсбольные мячи и наоборот.

Я выполнил запросы, в которых были обнаружены заказы, в которых были как бейсбольная бита, так и крикетный мяч, используя предложение HAVING (см. Код). Но проблема в том, что в том же порядке могла быть крикетная бита, что делает этот ордер действительным.

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

У меня есть данные уровня заказа, данные уровня строки и таблицы данных информации о продукте.

SELECT [LineLevelOrders.OrderNbr]
FROM LineLevelOrders
LEFT JOIN ItemInfo ON [LineLevelOrders.SKU] = [ItemInfo.SKU]
WHERE ( ([ItemInfo.Type] = 'Bats') AND ([ItemInfo.Range] = 'Cricket') ) 
   OR ( ([ItemInfo.Type] = 'Balls') AND ([ItemInfo.Range] = 'Baseballs') )
GROUP BY [LineLevelOrders.OrderNbr]
HAVING COUNT([LineLevelOrders.OrderNbr])>=2

Ответы [ 3 ]

0 голосов
/ 09 октября 2019

Вы можете установить все эти условия в предложении HAVING:

SELECT [LineLevelOrders.OrderNbr]
FROM LineLevelOrders LEFT JOIN ItemInfo 
ON [LineLevelOrders.SKU] = [ItemInfo.SKU]
GROUP BY [LineLevelOrders.OrderNbr]
HAVING 
  COUNT([LineLevelOrders.OrderNbr])>=2
  AND SUM(CASE WHEN [ItemInfo.Type] = 'Balls' AND [ItemInfo.Range] = 'Cricket' THEN 1 ELSE 0 END) > 0
  AND SUM(CASE WHEN [ItemInfo.Type] = 'Bats' AND [ItemInfo.Range] = 'Cricket' THEN 1 ELSE 0 END) = 0
  AND SUM(CASE WHEN [ItemInfo.Type] = 'Bats' THEN 1 ELSE 0 END) > 0
0 голосов
/ 09 октября 2019

Я думаю, что есть «лучший» способ сделать это, возможно, используя оконные функции. Но это должно быть функционально:

-- This CTE will return all order numbers that have Baseball Balls
;with BaseballBallsOrders_CTE as (
    select distinct OrderNbr
    from @LineLevelOrders llo
    inner join @ItemInfo ii on llo.SKU = ii.SKU
    where ii.Type = 'Balls'
        and ii.Range = 'Baseball'
),
-- This CTE will return all order numbers that have Cricket Balls
CricketBallsOrders_CTE as (
    select distinct OrderNbr
    from @LineLevelOrders llo
    inner join @ItemInfo ii on llo.SKU = ii.SKU
    where ii.Type = 'Balls'
        and ii.Range = 'Cricket'
),
-- This CTE will return all order numbers that DO NOT have Baseball Bats
NoBaseballBatsOrders_CTE as (
    select distinct OrderNbr
    from @LineLevelOrders
    where OrderNbr not in (select distinct OrderNbr
                           from @LineLevelOrders llo
                           inner join @ItemInfo ii on llo.SKU = ii.SKU
                           where ii.Type = 'Bats'
                                and ii.Range = 'Baseball'
                          )
),
-- This CTE will return all order numbers that DO NOT have Cricket Bats
NoCricketBatsOrders_CTE as (
    select distinct OrderNbr
    from @LineLevelOrders llo
    where OrderNbr not in (select distinct OrderNbr
                           from @LineLevelOrders llo
                           inner join @ItemInfo ii on llo.SKU = ii.SKU
                           where ii.Type = 'Bats'
                                and ii.Range = 'Cricket'
                          )
)

-- This first query combines orders that have Baseball Balls
-- AND do not have Baseball Bats
select BBallsO.OrderNbr
from BaseballBallsOrders_CTE BBallsO
inner join NoBaseballBatsOrders_CTE NoBBatsO on BBallsO.OrderNbr = NoBBatsO.OrderNbr

union
-- Union the above with this query that combines orders that have
-- Cricket Balls AND do not have Cricket Bats.
select CBallsO.OrderNbr
from CricketBallsOrders_CTE CBallsO
inner join NoCricketBatsOrders_CTE NoCBatsO on CBallsO.OrderNbr = NoCBatsO.OrderNbr
0 голосов
/ 09 октября 2019

Вы можете сначала повернуть, а затем отфильтровать так:

With ProductPivot AS
(
SELECT [LineLevelOrders.OrderNbr],
COUNT(IIF(([ItemInfo.Type] = 'Bats') AND ([ItemInfo.Range] = 'Cricket'),[LineLevelOrders.OrderNbr],NULL )) AS CricketBatsCount,
COUNT(IIF(([ItemInfo.Type] = 'Balls') AND ([ItemInfo.Range] = 'Baseballs'),[LineLevelOrders.OrderNbr],NULL )) AS BaseballBallsCount,
FROM LineLevelOrders
LEFT JOIN ItemInfo ON [LineLevelOrders.SKU] = [ItemInfo.SKU]
GROUP BY [LineLevelOrders.OrderNbr]
)
SELECT *
FROM ProductPivot
WHERE CricketBatsCount > 1 AND BaseballBallsCount > 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...