Home > front end >  How to get aggregate as a percentage of the total
How to get aggregate as a percentage of the total

Time:01-01

I have a table:

CREATE TABLE schools (
    ID int,
    type varchar(255)
);

INSERT INTO schools (ID, type)
VALUES (1, NULL),
(2, 'primary'),
(3, 'secondary'),
(4, 's'),
(5, 'p'),
(5, 'p');
ID Type
1 NULL
2 'primary'
3 'secondary'
4 's'
5 'p'
5 'p'

I need to produce a table like this:

Type Volume %
Primary 2 50
Secondary 2 50
Type      Volume %
Primary   2     50
Secondary 2     50

So far I have the first two columns by using the query:

SELECT CASE 
  WHEN type IN ('primary','p') THEN 'Primary'
  WHEN type IN ('secondary','s') THEN 'Secondary'
END Type,
count(distinct ID) as Volume
FROM t

I cant figure out how to get the Volume as a percentage. Using partition by and over keeps throwing aggregate errors. Could someone please explain how I can do this?

Also, I want the percentage to not include NULL, hence why it has 50%.

CodePudding user response:

Use SUM() window function to get the total:

SELECT CASE 
         WHEN type IN ('primary','p') THEN 'Primary'
         WHEN type IN ('secondary','s') THEN 'Secondary'
       END type,
       COUNT(*) AS Volume,
       100 * COUNT(*) / SUM(COUNT(*)) OVER () AS percentage
FROM (SELECT DISTINCT ID, type FROM schools) s
WHERE type IS NOT NULL
GROUP BY 1;

See the demo.

CodePudding user response:

You can use following query

SELECT Type,
       Volume,
       CAST(Volume AS Float) / SUM(Volume) OVER(PARTITION BY seq ORDER BY seq) * 100 AS '%'
FROM
   (SELECT Type,
        COUNT(DISTINCT ID) AS Volume,
        RANK() OVER(ORDER BY (SELECT NULL)) as seq
   FROM
      (SELECT ID,
        CASE 
         WHEN type IN ('primary','p') THEN 'Primary'
         WHEN type IN ('secondary','s') THEN 'Secondary'
        END Type
       FROM t) t
   WHERE Type IS NOT NULL
   GROUP BY Type) t

Demo in db<>fiddle

  • Related