#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;
В дополнение к вышесказанному, это позволяет упорядочивать результаты в хронологическом порядке и работает, если вы увеличиваете временные рамки более чем на один год.