#sql #postgresql #subquery #max
#sql #postgresql #подзапрос #максимальное
Вопрос:
Меня просят найти лучшего пользователя для разных стран, однако в одной из стран есть 2 пользователя с одинаковой потраченной суммой, поэтому они оба должны быть лучшими пользователями, но я не могу получить максимальное значение для 2 значений в этой стране. Вот код:
WITH t1 AS (
SELECT c.customerid,SUM(i.total) tot
FROM invoice i
JOIN customer c ON c.customerid = i.customerid
GROUP BY 1
ORDER BY 2 DESC
),
t2 AS (
SELECT c.customerid as CustomerId ,c.firstname as FirstName,c.lastname as LastName, i.billingcountry as Country,MAX(t1.tot) as TotalSpent
FROM t1
JOIN customer c
ON c.customerid = t1.customerid
JOIN invoice i ON i.customerid = c.customerid
GROUP BY 4
ORDER BY 4
)
SELECT *
FROM t2
BILLINGCOUNTRY находится в Invoice, и в нем есть название всех стран.
ОБЩАЯ сумма также указана в счете-фактуре и показывает, сколько тратится на каждую покупку Клиентом (поэтому для каждой покупки существуют разные сборы и налоги, а общая сумма показывает окончательную цену, уплаченную пользователем в каждый момент)
У клиента есть идентификатор, имя, фамилия, и из его идентификатора я извлекаю общую сумму каждой из его покупок
MAX использовался после нахождения суммы для каждого клиента и был СГРУППИРОВАН ПО странам, чтобы я мог найти максимальное значение для каждой страны, однако, похоже, я не могу найти максимальное значение последней страны, у которой было 2 максимальных значения
Ответ №1:
Используйте rank()
или dense_rank()
:
SELECT c.*, i.tot
FROM (SELECT i.customerid, i.billingCountry, SUM(i.total) as tot,
RANK() OVER (PARTITION BY i.billingCountry ORDER BY SUM(i.total) DESC) as seqnum
FROM invoice i
GROUP BY 1, 2
) i JOIN
customer c
ON c.customerid = i.customerid
WHERE seqnum = 1;
Подзапрос находит сумму на одного клиента в каждой стране — и, что важно, вычисляет рейтинг для комбинации со связями, имеющими одинаковый ранг. Внешний запрос просто вводит дополнительную информацию о клиенте, которая вам, похоже, нужна.
Комментарии:
1. он продолжает выдавать ошибку: сбой теста: рядом «(«: синтаксическая ошибка
2. из того, что я проверил, это действительно хорошая идея, но, возможно, она не работает, потому что система не позволяет нам использовать методы, отличные от того, что мы изучили. пробовал использовать UNION раньше, чтобы посмотреть, сработает ли это, если я добавлю последнюю запись вручную, и это все равно не сработало, поэтому, похоже, я вынужден использовать такие вещи, как RANK, WITH, HAVING, JOIN, GROUP BY …. и т. д
3. Не могли бы вы, пожалуйста, вставить весь запрос и в какой строке он выдает ошибку.
4. @Testuser1 . . . Синтаксис в порядке (как только я добавил отсутствующий псевдоним таблицы): dbfiddle.uk /… .
5. в этом проблема, это не дает мне, в какой строке была ошибка, и я скопировал тот же код, что и у вас, он тоже не сработал, так что, похоже, как я уже говорил вам, проблема в том, что система не позволяет нам использовать разные команды, которые мы не выполняли. « ВЫБЕРИТЕ c.*, i.tot ИЗ (ВЫБЕРИТЕ i.customerid, i.billingCountry, SUM (i.total) как tot, RANK() OVER (РАЗДЕЛИТЕ По i.billingCountry ORDER По SUM(i.total) DESC) как seqnum ИЗ счета, который я ГРУППИРУЮ ПО 1, 2 ) я ПРИСОЕДИНЯЮСЬ К клиенту c НА c.customerid = i.customerid ГДЕ seqnum = 1 ; « Сбой теста: рядом «(«: синтаксическая ошибка
Ответ №2:
вот как это сработало для меня, поскольку мне было запрещено использовать многие команды, такие как RIGHT JOIN
и RANK()
(как предложил Гордон Линофф), поэтому мне пришлось создать 3-й случай для anamoly и присоединиться к нему с помощью union. это решение работает только в этом случае, хорошим решением является то, которое опубликовал Гордон Линофф:
WITH t1 AS (
SELECT c.customerid,SUM(i.total) tot
FROM invoice i
JOIN customer c ON c.customerid = i.customerid
GROUP BY 1
ORDER BY 2 DESC
),
t2 AS (
SELECT c.customerid as CustomerId ,c.firstname as FirstName,c.lastname as LastName, i.billingcountry as Country,MAX(t1.tot) as TotalSpent
FROM t1
JOIN customer c
ON c.customerid = t1.customerid
JOIN invoice i ON i.customerid = c.customerid
GROUP BY 4
ORDER BY 4
) ,
t3 AS (
SELECT DISTINCT c.customerid as CustomerId ,c.firstname as FirstName,c.lastname as LastName, i.billingcountry as Country,t1.tot as TotalSpent
FROM t1
JOIN customer c
ON c.customerid = t1.customerid
JOIN invoice i ON i.customerid = c.customerid
WHERE i.billingcountry = 'United Kingdom'
ORDER BY t1.tot DESC
LIMIT 2
)
SELECT *
FROM t2
UNION
SELECT * FROM t3
ORDER BY t2.country