I have the following DB structure.
| id | projectname | number | filename | type | unq | count |
|---|---|---|---|---|---|---|
| 8 | prj1 | 2 | a | t1 | 888389f661e117 | 1 |
| 9 | prj1 | 2 | a | t1 | 888389f661e117 | 2 |
| 10 | prj1 | 2 | a | t1 | 888389f661e117 | 2 |
| 11 | prj1 | 2 | a | t2 | 816418549711c3d33 | 6 |
| 12 | prj1 | 2 | a | t2 | 816418549711c3d33 | 7 |
| 13 | prj1 | 2 | a | t2 | 816418549711c3d33 | 1 |
| 14 | prj1 | 2 | a | t3 | NULL | NULL |
| 15 | prj1 | 2 | a | t3 | NULL | NULL |
| 16 | prj1 | 2 | a | t3 | NULL | NULL |
| 17 | prj1 | 36 | b | t1 | 8dac5bdffc7f86502 | 0 |
| 18 | prj1 | 36 | b | t1 | 8dac5bdffc7f86502 | 0 |
| 19 | prj1 | 36 | b | t1 | 8dac5bdffc7f86502 | 0 |
I use the query below to get the sums of count column w.r.t. the type column. A unique identifier of a row is `(projectname, number, filename).
SELECT DISTINCT ON (projectname, number, type) number, type, SUM(count) as count
FROM myTable
GROUP BY (projectname, number, type)
ORDER BY number
which gives me the output
| number | type | count |
|---|---|---|
| 2 | t1 | 5 |
| 2 | t2 | 14 |
| 2 | t3 | NULL |
| 36 | t1 | 0 |
| 36 | t2 | 16 |
| 36 | t3 | NULL |
My ideal output is: for every number column item, I want to divide the t2 value by t1 and the t3 value to t2. Can I accomplish this with Postgres commands without using external data manipulation techniques? I am looking to obtain a table as below. The type column is just representative of the operation I am interested in.
| number | type | ratio |
|---|---|---|
| 2 | t2t1 | 14 by 5 |
| 2 | t3t2 | NULL by 14 is NULL |
| 36 | t2t1 | 16 by 0 is INF |
| 36 | t3t2 | NULL by 16 is NULL |
>Solution :
Based on your which gives me the output we can try to use LEAD and ROW_NUMBER window function to get next count and filter the latest row each number
SELECT number,
type,
CASE WHEN count = 0 THEN 'INF' ELSE (n_count::DECIMAL(8,3) /count )::VARCHAR(20) END
FROM (
SELECT *,
LEAD(count) OVER(PARTITION BY number ORDER BY type) n_count,
ROW_NUMBER() OVER(PARTITION BY number ORDER BY type DESC) rn
FROM (
SELECT DISTINCT ON (projectname, number, type) number, type, SUM(count) as count
FROM myTable
GROUP BY (projectname, number, type)
ORDER BY number
) t1
) t1
WHERE rn > 1
but I saw full sample data and expect result you might need to use OUTER JOIN based on type,number which is created by CROSS JOIN
WITH CTE AS (
SELECT *
FROM (
SELECT distinct type
FROM myTable
) t1 CROSS JOIN (
SELECT distinct number
FROM myTable
) t2
)
SELECT number,
type,
CASE WHEN count = 0 THEN 'INF' ELSE (n_count::DECIMAL(8,3) /count )::VARCHAR(20) END
FROM (
SELECT *,
LEAD(count) OVER(PARTITION BY number ORDER BY type) n_count,
ROW_NUMBER() OVER(PARTITION BY number ORDER BY type DESC) rn
FROM (
SELECT t1.number, t1.type, SUM(t2.count) count
FROM CTE t1
LEFT JOIN myTable t2
ON t1.type = t2.type
AND t1.number = t2.number
GROUP BY t1.number, t1.type
) t1
) t1
WHERE rn > 1