我有这张桌子
ID value user stock ----|--------|---------|--------- 1 | 10 | mark | AAPL 2 | 20 | rob | GOOG 3 | 30 | mark | AAPL 4 | -40 | mark | AAPL 5 | -10 | rob | GOOG 6 | 25 | mark | GOOG 7 | 5 | mark | GOOG 8 | 45 | mark | AAPL
我想构建一个返回下面显示的行的查询(可能不使用任何PGSQL函数)。它应该按顺序开始(ID ASC)求和"值"按用户,库存分组的列。如果临时总和为0,则将丢弃所有先前的行(针对该组)。
id value user stock ----|--------|---------|--------- 2 | 20 | rob | GOOG 5 | -10 | rob | GOOG 6 | 25 | mark | GOOG 7 | 5 | mark | GOOG 8 | 45 | mark | AAPL
我认为应该使用OVER(PARTITION BY)和WINDOW函数
SELECT *, SUM(value) OVER w AS scm
FROM "mytable"
WINDOW w AS (PARTITION BY user,stock ORDER BY id ASC)
这将返回下一个表
ID value user stock scm ----|--------|---------|---------|------- 1 | 10 | mark | AAPL | 10 2 | 20 | rob | GOOG | 20 3 | 30 | mark | AAPL | 40 4 | -40 | mark | AAPL | 0 5 | -10 | rob | GOOG | 10 6 | 25 | mark | GOOG | 25 7 | 5 | mark | GOOG | 30 8 | 45 | mark | AAPL | 45
所以这应该是一个很好的起点,因为它表明APPL对于mark是0(id = 4),对于那个组(AAPL,mark),我应该保留以下所有行。 规则是:对于每个组(stock,user),使用scm = 0
保留最后一行之后的所有行答案 0 :(得分:1)
with s as (
select *,
count(scm = 0 or null) over w z
from (
select *,
sum(value) over w as scm
from mytable
window w as (partition by "user", stock order by id asc)
) s
window w as (partition by "user", stock order by id asc)
)
select *
from
s
inner join
(
select max(z) z, "user", stock
from s
group by "user", stock
) z using (z, "user", stock)
where scm > 0
order by s.user, s.stock, id
答案 1 :(得分:0)
以下我认为会让你想要的东西。基本上它将执行以下操作:
(username, stock)
组应显示的最小ID。WITH sums AS (
SELECT id, value, username, stock, SUM(value) OVER w AS scm
FROM "mytable"
WINDOW w AS (PARTITION BY user,stock ORDER BY id ASC)),
minimum_ids AS (
SELECT username, stock, MAX(id) as minimum_id
FROM sums
WHERE scm <= 0
GROUP BY username, stock)
SELECT sums.id, sums.value, sums.username, sums.stock, sums.scm
FROM sums
LEFT JOIN minimum_ids
ON (sums.username = minimum_ids.username
AND sums.stock = minimum_ids.stock)
WHERE (minimum_ids.minimum_id IS NULL OR sums.id > minimum_ids.minimum_id)
ORDER BY id;