Вы можете использовать оконные функции, чтобы получить номер ранга, а затем использовать нормальную агрегацию с SUM
:
WITH cte AS
(
SELECT *, RANK() OVER(PARTITION BY userid ORDER BY "date" DESC) AS r
FROM purchase
)
SELECT SUM(price) AS total
FROM cte
WHERE r = 1;
SqlFiddleDemo
Имейте в виде, что это решение вычисляет связь. Чтобы получить только одну покупку на одного пользователя, вам нужен столбец, который отличается для каждой группы (например, datetime
). Но все же это возможность получить связи.
EDIT:
Handling связи:
CREATE TABLE purchase(
userid INTEGER NOT NULL
,date timestamp NOT NULL
,price INTEGER NOT NULL
);
INSERT INTO purchase(userid,date,price) VALUES
(1, timestamp'2016-01-06 12:00:00',10),
(1,timestamp'2016-01-05',5),
(2,timestamp'2016-01-06 13:00:00',12),
(2,timestamp'2016-01-05',15),
(2,timestamp'2016-01-06 13:00:00',1000)'
Обратите внимание на разницу RANK()
против ROW_NUMBER
:
SqlFiddleDemo_RANK
SqlFiddleDemo_ROW_NUMBER
SqlFiddleDemo_ROW_NUMBER_2
Выход:
╔════════╦══════════════╦══════════════╗
║ RANK() ║ ROW_NUMBER() ║ ROW_NUMBER() ║
╠════════╬══════════════╬══════════════╣
║ 1022 ║ 22 ║ 1010 ║
╚════════╩══════════════╩══════════════╝
Без UNIQUE
индекс userid/date
всегда есть возможность (возможно, небольшой) для галстука. Любые решения, основанные на ORDER BY
, должны работать стабильно.
Может ли пользователь иметь более одной покупки в день? – Elad
Да, я могу, но нормально, у меня также есть время в столбце даты. Так что это не должно быть проблемой. – cheb1k4