Использование SELECT с INNER JOIN и WHILE - PullRequest
0 голосов
/ 07 ноября 2019

Я хочу понять это на этом "простом" примере запроса. Я хочу просматривать даты и идентификаторы заказов с наибольшей стоимостью заказа (прибыли) в каждом квартале 1997 года. Я могу написать что-то вроде этого.

SELECT o.OrderDate, o.OrderID, DATEPART(QUARTER, o.OrderDate)
FROM Orders o INNER JOIN (SELECT...)
WHERE YEAR(o.OrderDate) = '1997'
GROUP BY o.OrderDate, o.OrderID; 

OrderDetails содержит стоимость заказа (цену). Поймайте, я не хочу просматривать значение, поэтому мне нужно использовать SELECT с INNER JOIN или WHILE (возможно, INNER JOIN в этом случае). Я пробовал несколько решений, и он показывает более 800 строк, когда он должен возвращать только 4 строки. Также есть проблема, что GROUP BY не будет работать должным образом с OrderDate.

Я ожидаю, что результаты будут такими:

Order date | OrderID | Quarter
05.02.1997 | 173412  | 1
05.04.1997 | 421552  | 2
12.07.1997 | 735245  | 3
24.12.1997 | 825425  | 4

Запрос с небольшим объяснением будет высоко оценен.

1 Ответ

0 голосов
/ 07 ноября 2019

Возможно, вам нужен какой-нибудь оконный агрегат:

with cte as
 (
   SELECT *,
      -- "highest value" per quarter
      max(whatever)
      over (partition by DATEPART(QUARTER, o.OrderDate)) as max_value
   FROM OrderDetails od INNER JOIN Orders o ON od.OrderID = o.OrderID
   WHERE YEAR(o.OrderDate) = '1997'
 ) 
select distinct
   o.OrderDate, o.OrderID, DATEPART(QUARTER, o.OrderDate)
from cte
-- current value = highest value of the quarter 
where whatever = max_value 

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

with cte as
 (
   SELECT *,
      -- "highest value" per quarter = row_number 1
      row_number()
      over (partition by DATEPART(QUARTER, o.OrderDate)
            order by whatever desc) as rn
   FROM OrderDetails od INNER JOIN Orders o ON od.OrderID = o.OrderID
   WHERE YEAR(o.OrderDate) = '1997'
 ) 
select o.OrderDate, o.OrderID, DATEPART(QUARTER, o.OrderDate)
from cte
-- "highest value" per quarter = row_number 1
where rn = 1 

Если вы настаиваете на использовании старого SQL, вы можете сделать то же самое без использования оконных агрегатов (но более сложным и, вероятно, менее эффективным). ):

with cte as
 ( -- prepare the base data to avoid writing the same join/where twice
   SELECT o.OrderDate, o.OrderID, DATEPART(QUARTER, o.OrderDate) as q, whatever
   FROM OrderDetails od INNER JOIN Orders o
     ON od.OrderID = o.OrderID
   WHERE YEAR(o.OrderDate) = '1997'
 )
SELECT DISTINCT t1.OrderDate, t1.OrderID, t1.q
FROM cte
join 
 ( 
   select q, 
      -- "highest value" per quarter
      max(whatever) as max_value
   from cte
   group by q
 ) as maxperq
on cte.q = maxperq.q  -- same quarter
and cte.whatever = maxperq.whatever -- highest value of the quarter
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...