Snažím se vytvořit průběžný součet, ale třeba poslední hodnotu pro každý řádek v jiné tabulce. V následujícím příkladu, mohu snadno vyrábět průběžný součet pro každou time
hodnota v T
, ale rád bych se běží celkem T
pro každou hodnotu času v P
(spíše než pro každou transakci v T
dostat cenu, což je triviální):
Dané tabulky transakcí T
jako:
uživatel | hodinu | položka | delta |
---|---|---|---|
Alice | 1 | A | 1 |
Alice | 1 | A | 2 |
Bob | 2 | A | 2 |
Alice | 3 | A | 1 |
Bob | 3 | B | 1 |
Alice | 5 | A | -1 |
Bob | 5 | B | 3 |
A cenová tabulka P
jako:
hodinu | položka | cena |
---|---|---|
1 | A | 1.1 |
1 | B | 1.2 |
2 | A | 2.1 |
2 | B | 2.2 |
3 | A | 3.1 |
3 | B | 3.2 |
4 | A | 4.1 |
4 | B | 4.2 |
5 | A | 5.1 |
5 | B | 5.2 |
Rád bych záznam pro každou hour
v P
kde user
běží celkem je non-nulové. Něco jako:
hodinu | položka | cena | uživatel | running_total |
---|---|---|---|---|
1 | A | 1.1 | Alice | 3 |
2 | A | 2.1 | Alice | 3 |
2 | A | 2.1 | Bob | 2 |
3 | A | 3.1 | Alice | 4 |
3 | A | 3.1 | Bob | 2 |
3 | B | 3.2 | Bob | 1 |
4 | A | 4.1 | Alice | 4 |
4 | A | 4.1 | Bob | 2 |
4 | B | 4.2 | Bob | 1 |
5 | A | 5.1 | Alice | 3 |
5 | A | 5.1 | Bob | 2 |
5 | B | 5.2 | Bob | 4 |
Jsem v pořádku s nulami nebo null
s místo řádků jsem zmenšován (tj. před Bob s žádné položky). Zásadní věc, kterou mám problémy, je, že na každou hodinu, kde položka má cenu, rád bych každý uživatel je rovnováha.
Já jsem v současné době dělá to velmi hloupě, v procedurální jazyk, iterace přes všechny hour
hodnoty v P
- ale vzhledem k tomu, že si myslím, že jen hledám filtrované kartézský součin mezi tabulkou a běží celkem tabulky, myslím, že tam musí být lepší způsob, jak to udělat.
Moje aktuální řešení iterace přes cenovou tabulku (~3K řádků v tabulce cen, 10K řádků transakcí v tabulce) trvá asi 250 ms dělat povinně. Následující SQL zdá se, že dělat svou práci, ale trvá ~25 sekund, takže jsem doufal, že existuje lepší způsob, jak dělat věci:
with ranked_b as (
select F.*, row_number() over (partition by p_hour, user, item order by hour desc) as rn
from (select P.hour as p_hour, P.price, B.* from P cross join (select distinct a.hour, a.user, a.item, sum(a.delta) over (partition by a.user, a.item order by a.hour) running_total from T a order by a.hour) B on P.item=B.item and B.hour<=P.hour order by P_hour, B.user, B.item, B.hour) F
) SELECT p_hour as hour, item, price, user, running_total from ranked_b where rn=1;