Выберите наивысший доставленный заказ

#sql #oracle

#sql #Oracle

Вопрос:

Ниже приведен мой вывод:

 MONTH STAF STAFFNAME            TOTAL_ORDER_DELIVERED
===== ==== ==================== =====================
JAN   S009 Theresina Ertelt                         1
FEB   S015 Lonna Charker                            1
MAR   S003 Suzi Maccari                             2
MAR   S010 Zacharie Witty                           1
MAR   S020 Abbie Gosnoll                            1
MAR   S017 Renee Alston                             1
AUG   S006 Falito Ollerton                          1
AUG   S017 Renee Alston                             1
AUG   S003 Suzi Maccari                             1
OCT   S003 Suzi Maccari                             3
OCT   S020 Abbie Gosnoll                            2
  

Чего я хочу, так это:

 MONTH STAF STAFFNAME            TOTAL_ORDER_DELIVERED
===== ==== ==================== =====================
JAN   S009 Theresina Ertelt                         1
FEB   S015 Lonna Charker                            1
MAR   S003 Suzi Maccari                             2
AUG   S006 Falito Ollerton                          1
AUG   S017 Renee Alston                             1
AUG   S003 Suzi Maccari                             1
OCT   S003 Suzi Maccari                             3
  

Я хочу выбрать наивысший результат на основе месяца, но не могу понять, что делать. Вот мой запрос в SQL:

 SELECT TO_CHAR(TO_DATE(EXTRACT(MONTH FROM receivedDate),'mm'),'MON') AS Month,
       d.staffID, staffname, count(deliveryID) AS Total_Order_Delivered
FROM delivery d, deliverystaff s
WHERE (d.staffid = s.staffid)
AND (EXTRACT(YEAR FROM receivedDate) = 2020)
GROUP BY EXTRACT(MONTH FROM d.receivedDate),d.staffid, staffname 
ORDER BY EXTRACT(MONTH FROM d.receivedDate),count(deliveryID) desc;
  

Ответ №1:

Я бы предложил использовать RANK здесь:

 WITH cte AS (
    SELECT TO_CHAR(TO_DATE(EXTRACT(MONTH FROM receivedDate), 'mm'), 'MON') AS Month,
           EXTRACT(MONTH FROM d.receivedDate) AS month_num,
           d.staffID, staffname, COUNT(deliveryID) AS Total_Order_Delivered,
           RANK() OVER (PARTITION BY EXTRACT(MONTH FROM d.receivedDate), d.staffid, staffname
                        ORDER BY COUNT(deliveryID) DESC) rnk
    FROM delivery d
    INNER JOIN deliverystaff s ON d.staffid = s.staffid
    WHERE EXTRACT(YEAR FROM receivedDate) = 2020
    GROUP BY EXTRACT(MONTH FROM d.receivedDate), d.staffid, staffname
)

SELECT Month, staffID, staffname, Total_Order_Delivered
FROM cte
WHERE rnk = 1
ORDER BY month_num;
  

Ответ №2:

Ответ Тима в порядке. Тем не менее, я настоятельно рекомендую вам внести некоторые изменения в запрос.

Во-первых, для where предложения не используйте extract() . Используйте прямое сравнение дат. Во-вторых, включите год и месяц в агрегацию. Затем убедитесь, что вы указали все ссылки на столбцы.

Это позволяет вам делать:

 SELECT sd.*
FROM (SELECT TO_CHAR(d.receivedDate, 'YYYY-MON') AS Month_year,
             s.staffID, s.staffname, COUNT(*) AS Total_Order_Delivered,
             RANK() OVER (PARTITION BY TO_CHAR(d.receivedDate, 'YYYY-MON') ORDER BY COUNT(*) DESC) as seqnum,
              MIN(d.receiveddate) as min_receiveddate
      FROM deliverystaff s JOIN
           delivery d
           ON d.staffid = s.staffid
      WHERE d.receivedDate >= DATE '2020-01-01' AND 
            d.receivedDate < DATE '2021-01-01'
      GROUP BY TO_CHAR(d.receivedDate, 'YYYY-MON') AS Month,
               s.staffID, s.staffname 
     ) sd
WHERE seqnum = 1
ORDER BY min_receiveddate;
  

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