Consider this data (View on DB Fiddle):
| id | dept | value |
|---|---|---|
| 1 | A | 5 |
| 1 | A | 5 |
| 1 | B | 7 |
| 1 | C | 5 |
| 2 | A | 5 |
| 2 | A | 5 |
| 2 | B | 15 |
| 2 | A | 2 |
The base query I am running is pretty simple. Just get the total value by id and the most frequent dept.
SELECT
id,
MODE() WITHIN GROUP(ORDER BY dept) AS dept_freq,
SUM(value) AS value
FROM test
GROUP BY id
;
| id | dept_freq | value |
|---|---|---|
| 1 | A | 22 |
| 2 | A | 27 |
But I also need to get, for each id, the dept that concentrates the greatest value (so the greatest sum of value by id and dept, not the highest individual value in the original table).
Is there any way to use window functions to achieve that and do it directly in the base query above?
The expected output for this particular example would be:
| id | dept_freq | dept_value | value |
|---|---|---|---|
| 1 | A | A | 22 |
| 2 | A | B | 27 |
I could achieve that with the query below and then joining that with the results of the base query above
SELECT * FROM(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY id ORDER BY value DESC) as row
FROM (
SELECT id, dept, SUM(value) AS value
FROM test
GROUP BY id, dept
) AS alias1
) AS alias2
WHERE alias2.row = 1
;
| id | dept | value | row |
|---|---|---|---|
| 1 | A | 10 | 1 |
| 2 | B | 15 | 1 |
But it is not easy to read/maintain and seems also pretty inefficient. So I thought it should be possible to achieve this using window functions directly in the base query, and that also may also help Postgres to come up with a better query plan that does less passes over the data. But none of my attempts using over partition and filter worked.