Reputation: 4305
I can't seem to understand how to do a simple thing in a single query.
I have a table containing balance of items present in system at end of every day:
CREATE TEMPORARY TABLE t1 (
item character varying(10),
storage_date date,
qty integer
);
COPY t1 (item, storage_date, qty) FROM stdin;
A 2021-01-01 10
A 2021-01-02 10
A 2021-01-03 10
A 2021-01-04 5
A 2021-01-05 3
B 2021-01-01 1
B 2021-01-02 2
B 2021-01-03 100
B 2021-01-04 50
\.
I need to get average number of items stored per period along with the balance of each item at the end of period.
Let's say the period is between 2021-01-01 and 2021-01-05 .
Now, of course, average is simply:
SELECT item, sum(qty)/5 FROM t1 GROUP BY item ORDER BY item;
item | avg
------+-----
A | 7
B | 30
(2 rows)
But I need it to also include the balance (qty) for each item for the last date of the period = 2021-01-05 (As you can see, item B also has no entry for that date, meaning the stock was 0 at that point. But it is OK, if it is either NULL or 0). Wanted:
item | avg | balance at end of period
------+-----+---------
A | 7 | 3
B | 30 | NULL
(2 rows)
I tried to use last_value() aggregate function:
SELECT item,last_value(qty) OVER (ORDER BY storage_date),sum(qty)/5 from t1 group by 1,2;
But that obviously doesn't work (I am not fluent at more advanced SQL; JOINS, GROUP BY and HAVING is what I understand).
What am I missing? Surely there must be some simple way rather than writing two queries?
Upvotes: 1
Views: 847
Reputation: 1269563
You can use a subquery:
SELECT item, sum(qty)/5, balance
FROM (SELECT t1.*,
FIRST_VALUE(qty) OVER (PARTITION BY item ORDER BY storage_date DESCk) as balance
FROM t1
) t1
GROUP BY item, balance
ORDER BY item;
You can do this without a subquery as well:
I'm not sure why you are using SUM(qty) / 5
instead of AVG(qty)
, but that logic is from your query.
SELECT item, sum(qty)/5,
(ARRAY_AGG(qty ORDER BY storage_date DESC))[1] as balance
FROM t1
GROUP BY item
ORDER BY item;
Upvotes: 2
Reputation: 22811
You can use LEFT JOIN
SELECT ta.*, tb.qty
FROM(
SELECT item, sum(qty)/5
FROM t1
GROUP BY item) ta
LEFT JOIN t1 tb ON ta.item = tb.item AND tb.storage_date = TO_DATE('20210105','YYYYMMDD')
ORDER BY item;
Upvotes: 1