Как выбрать максимальное значение после SUM () + Group By?
у меня есть выпускной экзамен SQL в колледже через несколько дней, и у меня есть запрос, который сводит меня с ума! Я знаю, что это глупый вопрос, но я только начинаю и не могу понять.
Итак, есть основные 2 таблицы, клиент и заказы.
Client Orders
--------- ---------
PK Client_Id PK Order_Id
Name Client_Id FK
Order_Total
Date
теперь они просят меня "список именем клиента, который купил больше всего в 2011 году"
Итак, для того, что я думал, это требует с одной стороны, чтобы я суммировал все Order_Total и Group BY Client из 2011, затем из этой таблицы выберите клиента с максимальной () суммой итогов заказа, а затем покажите только имя этого клиента. Проблема в том, что я не могу понять, как поместить все это в один запрос.
надеюсь, что кто-то может помочь!
спасибо всем за очень быстрые ответы! Я действительно впечатлен!
теперь, я не хочу быть придирчивым или что-то еще, но на всякий случай, если мой учитель не принимает оператор "Limit" или "Select top" , есть ли способ сделать этот запрос без них?
Edit: попытка исходного кода портирована из комментариев:
SELECT
C.NAME
FROM
CLIENTS C,
ORDERS O
WHERE
O.CLIENT_ID = C.CLIENT_ID
AND O.DATE BETWEEN '1/1/2011 00:00:00.000' and '12/31/2011 23:59:59.999'
HAVING SUM(O.ORDER_TOTAL) >= ALL (SELECT SUM (O2.ORDER_TOTAL) FROM ORDER O2 GROUP BY O2.CLIENT_ID)
5 ответов
SELECT T.X
(SELECT C.NAME X, SUM(O.ORDER_TOTAL)
FROM CLIENT C, ORDERS O
WHERE C.CLIENT_ID = O.CLIENT_ID
AND YEAR(O.DATE) = 2011
GROUP BY O.CLIENT_ID
ORDER BY 2 DESC
LIMIT 1) T;
есть много способов, чтобы кожа Этот кот... вот как я обычно это делаю:
select top 1 c.Client_Id, c.Name, o.Order_Total
from Client c
join (select Client_Id, SUM(Order_Total) as Order_Total
from Orders
where `Date` between '1/1/2011 00:00:00.000' and '12/31/2011 23:59:59.999'
group by Client_Id) o
on c.Client_Id = o.Client_Id
order by o.Order_Total desc
в основном вы вытягиваете список всего заказа, присоединяясь к нему, сортируя его по убыванию по сумме заказа и ограничивая запрос результатом 1.
вы почти там, вам просто нужно выбрать из вашего совокупного запроса. Это называется производной таблицей.
Так что у вас есть это:
select c.client_id, c.name, sum(order_total) ordersum
from client c
inner join orders o on c.client_id = o.client_id
where year(o.date) = 2011
group by c.client_id, c.name
это дает вам ваши суммы. Теперь тебе нужен первый. Существует несколько способов сделать это, и это также зависит от того, какие СУБД вы используете (mysql, mssql и т. д.) Самый простой метод, однако, таков:
select top 1 *
from (
select c.client_id, c.name, sum(order_total) ordersum
from client c
inner join orders o on c.client_id = o.client_id
where year(o.date) = 2011
group by c.client_id, c.name
) a
order by ordersum desc
на данной платформе может быть что-то проще, но этот запрос должен быть достаточно общим для работы какие бы СУБД вы ни использовали.
ответ Is7aq правильный в соответствии с вашим вопросом, но будет работать только на MySQL. Также не учитывается возможность того, что более одного клиента купили больше всего в данном году, хотя я признаю, что это не было ограничением, перечисленным в исходном вопросе. Также это огромный удар по производительности, чтобы пересечь соединения, просто используя запятые, как только ваши базы данных станут достаточно большими, поэтому почти всегда лучше использовать внутренние или внешние соединения и указать условие соединения. В любом случае, это как упражнение и вот что у меня было. Это, вероятно, может быть лучше оптимизировано:
CREATE TABLE #Client (
Client_Id int not null,
Name varchar(100) not null
)
INSERT INTO #Client VALUES (1, 'Client 1')
INSERT INTO #Client VALUES (2, 'Client 2')
INSERT INTO #Client VALUES (3, 'Client 3')
CREATE TABLE #Orders (
Order_Id int not null,
Client_Id int not null,
Order_Total int not null,
Date datetime not null
)
-- Customer 1: total=105
INSERT INTO #Orders VALUES (1, 1, 55, '1/1/2011')
INSERT INTO #Orders VALUES (2, 1, 50, '1/1/2011')
INSERT INTO #Orders VALUES (3, 1, 45, '1/1/2010') -- test removal of invalid dates
-- Customer 2: total=120
INSERT INTO #Orders VALUES (4, 2, 40, '1/1/2011')
INSERT INTO #Orders VALUES (5, 2, 40, '1/1/2011')
INSERT INTO #Orders VALUES (6, 2, 40, '1/1/2011')
-- Customer 3: total=120
INSERT INTO #Orders VALUES (7, 3, 40, '1/1/2011')
INSERT INTO #Orders VALUES (8, 3, 40, '1/1/2011')
INSERT INTO #Orders VALUES (9, 3, 40, '1/1/2011')
-- control customer to test hi/lo scenarios: total=40
INSERT INTO #Orders VALUES (10, 4, 10, '1/1/2011')
INSERT INTO #Orders VALUES (11, 4, 10, '1/1/2011')
INSERT INTO #Orders VALUES (12, 4, 10, '1/1/2011')
INSERT INTO #Orders VALUES (13, 4, 10, '1/1/2011')
SELECT T.NAME,
T.OrderTotal
FROM (SELECT C.NAME,
SUM(O.ORDER_TOTAL) OrderTotal
FROM #CLIENT C
INNER JOIN #ORDERS O
ON c.CLIENT_ID = o.CLIENT_ID
WHERE YEAR(O.DATE) = 2011
GROUP BY C.NAME) as T
WHERE T.OrderTotal = (SELECT MAX(T2.OrderTotal2)
FROM (SELECT C2.NAME,
SUM(O2.ORDER_TOTAL) OrderTotal2
FROM #CLIENT C2
INNER JOIN #ORDERS O2
ON c2.CLIENT_ID = o2.CLIENT_ID
WHERE YEAR(O2.DATE) = 2011
GROUP BY C2.NAME) as T2)
GROUP BY T.Name, T.OrderTotal
DROP TABLE #Client
DROP TABLE #Orders
-- Output
-- Client 2: 120
-- Client 3: 120
SELECT Client.Name
FROM Client LEFT JOIN Orders ON Orders.Client_Id = Client.Client_Id
WHERE YEAR(Orders.Date) = 2011
GROUP BY Client.Client_Id
ORDER BY SUM(Order.Order_Total) DESC
LIMIT 1