103

I have a table with 2 fields:

ID  Name
--  -------
1   Alpha
2   Beta
3   Beta
4   Beta
5   Charlie
6   Charlie

I want to group them by name, with 'count', and a row 'SUM'

Name     Count
-------  -----
Alpha     1
Beta      3
Charlie   2
SUM       6

How would I write a query to add SUM row below the table?

Braiam
  • 1
  • 11
  • 47
  • 78
nametal
  • 1,451
  • 2
  • 14
  • 18
  • 4
    If you need the sum in the select itself to calculate with it, use a subselect: `SELECT Name, COUNT(*) AS amount, COUNT(*)/total.total * 100 AS percentage, total.total FROM temp, ( SELECT COUNT(*) AS total FROM temp ) AS total GROUP BY Name` [See SQLfiddle](http://sqlfiddle.com/#!2/0480d/8) – yunzen May 02 '14 at 10:27
  • Beware in the answers below--There is no guaranteed order in a query result without ORDER BY. – philipxy Jun 21 '19 at 09:14

17 Answers17

113
SELECT name, COUNT(name) AS count, SUM(COUNT(name)) OVER() AS total_count
FROM Table GROUP BY name
Yitzchok Glancz
  • 1,302
  • 1
  • 10
  • 9
106
SELECT name, COUNT(name) AS count
FROM table
GROUP BY name

UNION ALL

SELECT 'SUM' name, COUNT(name)
FROM table

OUTPUT:

name                                               count
-------------------------------------------------- -----------
alpha                                              1
beta                                               3
Charlie                                            2
SUM                                                6
Erikw
  • 799
  • 6
  • 18
Vishal Suthar
  • 17,013
  • 3
  • 59
  • 105
  • 1
    Valid answer. Please look at @Adriann's answer using rollup. http://stackoverflow.com/a/12927333/2012977 – Osa E Nov 11 '15 at 17:49
  • What is `Union all` ? EDIT : ok i was confused because of its indentation. It's juste union-ing the 2 selectors :) – mcoenca Aug 11 '17 at 10:00
20

Without specifying which rdbms you are using

Have a look at this demo

SQL Fiddle DEMO

SELECT Name, COUNT(1) as Cnt
FROM Table1
GROUP BY Name
UNION ALL
SELECT 'SUM' Name, COUNT(1)
FROM Table1

That said, I would recomend that the total be added by your presentation layer, and not by the database.

This is a bit more of a SQL SERVER Version using Summarizing Data Using ROLLUP

SQL Fiddle DEMO

SELECT CASE WHEN (GROUPING(NAME) = 1) THEN 'SUM'
            ELSE ISNULL(NAME, 'UNKNOWN')
       END Name, 
      COUNT(1) as Cnt
FROM Table1
GROUP BY NAME
WITH ROLLUP
Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
  • Shouldn't the second select be a sum, not a count? – Greg Oct 17 '12 at 04:55
  • @Greg, it should be sum if you were re-referincing the statement at the top, maybe using a WITH CTE statement ( Sql Server). – Adriaan Stander Oct 17 '12 at 04:57
  • 1
    Thanks for pointing out rollup. Your answer should be the accepted answer. We have huge tables and hate hitting the table twice. – Osa E Nov 11 '15 at 17:48
14

Try this:

SELECT  ISNULL(Name,'SUM'), count(*) as Count
FROM table_name
Group By Name
WITH ROLLUP
smoore4
  • 4,520
  • 3
  • 36
  • 55
Koy Bun
  • 201
  • 1
  • 6
9

all of the solution here are great but not necessarily can be implemented for old mysql servers (at least at my case). so you can use sub-queries (i think it is less complicated).

 select sum(t1.cnt) from 
        (SELECT column, COUNT(column) as cnt
            FROM
            table 
            GROUP BY 
            column
            HAVING 
            COUNT(column) > 1) as t1 ;
Itay wazana
  • 229
  • 2
  • 9
5

Please run as below :

Select sum(count) 
  from (select Name, 
               count(Name) as Count 
          from YourTable
      group by Name);  -- 6
drneel
  • 2,887
  • 5
  • 30
  • 48
5

The way I interpreted this question is needing the subtotal value of each group of answers. Subtotaling turns out to be very easy, using PARTITION:

SUM(COUNT(0)) OVER (PARTITION BY [Grouping]) AS [MY_TOTAL]

This is what my full SQL call looks like:

SELECT MAX(GroupName) [name], MAX(AUX2)[type],  
COUNT(0) [count], SUM(COUNT(0)) OVER(PARTITION BY GroupId) AS [total]
    FROM [MyView]
  WHERE Active=1 AND Type='APP' AND Completed=1
    AND [Date] BETWEEN '01/01/2014' AND GETDATE()
    AND Id = '5b9xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' AND GroupId IS NOT NULL
  GROUP BY AUX2, GroupId

The data returned from this looks like:

name    type    count   total
Training Group 2    Cancelation 1   52
Training Group 2    Completed   41  52
Training Group 2    No Show 6   52
Training Group 2    Rescheduled 4   52
Training Group 3    NULL        4   10535
Training Group 3    Cancelation 857 10535
Training Group 3    Completed   7923    10535
Training Group 3    No Show 292 10535
Training Group 3    Rescheduled 1459    10535
Training Group 4    Cancelation 2   27
Training Group 4    Completed   24  27
Training Group 4    Rescheduled 1   27
Juls
  • 658
  • 6
  • 15
2

You can use union to joining rows.

select Name, count(*) as Count from yourTable group by Name
union all
select "SUM" as Name, count(*) as Count from yourTable
Habibillah
  • 27,347
  • 5
  • 36
  • 56
2

For Sql server you can try this one.

SELECT ISNULL([NAME],'SUM'),Count([NAME]) AS COUNT
FROM TABLENAME
GROUP BY [NAME] WITH CUBE
sapan
  • 21
  • 3
1
  with cttmp
  as
  (
  select Col_Name, count(*) as ctn from tab_name group by Col_Name having count(Col_Name)>1
  )
  select sum(ctn) from c
Bendy
  • 3,506
  • 6
  • 40
  • 71
Masum
  • 119
  • 11
1

You can use ROLLUP

select nvl(name, 'SUM'), count(*)
from table
group by rollup(name)
Yitzchok Glancz
  • 1,302
  • 1
  • 10
  • 9
0

Use it as

select Name, count(Name) as Count from YourTable
group by Name
union 
Select 'SUM' , COUNT(Name) from YourTable
Usman
  • 3,200
  • 3
  • 28
  • 47
  • I choose UNION ALL instead of UNION to place the 'SUM' row at the bottom (according to @VishalSuthar's answer above) – nametal Oct 17 '12 at 06:01
  • i think you misinterpret UNION and UNION ALL `UNION removes duplicate records (where all columns in the results are the same), UNION ALL does not.` thats Y i used UNION – Usman Oct 17 '12 at 06:48
  • thanks for your correction, but in this case, I must place 'SUM' on the bottom line which is can be done by using UNION ALL – nametal Oct 17 '12 at 08:16
  • do you try it with using UNION?as i have tried it must place 'SUM' at the bottom, but as far as the performance is concern UNION ALL is good in your scenario, because UNION is much less performant as it must scan the result for duplicates.. – Usman Oct 17 '12 at 11:04
  • I've tried it in larger database and it place 'SUM' at around the middle of table (not always at the bottom). Anyway, I got the point of difference between UNION ALL and UNION, thanks – nametal Oct 17 '12 at 14:18
0

I am using SQL server and the following should work for you:

select cast(name as varchar(16)) as 'Name', count(name) as 'Count' from Table1 group by Name union all select 'Sum:', count(name) from Table1

0

I required having count(*) > 1 also. So, I wrote my own query after referring some the above queries

SYNTAX:

select sum(count) from (select count(`table_name`.`id`) as `count` from `table_name` where {some condition} group by {some_column} having count(`table_name`.`id`) > 1) as `tmp`;

Example:

select sum(count) from (select count(`table_name`.`id`) as `count` from `table_name` where `table_name`.`name` IS NOT NULL and `table_name`.`name` != '' group by `table_name`.`name` having count(`table_name`.`id`) > 1) as `tmp`;
theBuzzyCoder
  • 2,652
  • 2
  • 31
  • 26
-2

You can try group by on name and count the ids in that group.

SELECT name, count(id) as COUNT FROM table group by name
Htaras
  • 849
  • 1
  • 7
  • 17
-2

After the query, run below to get the total row count

select @@ROWCOUNT
Chitta
  • 206
  • 2
  • 6
-6

select sum(s) from (select count(Col_name) as s from Tab_name group by Col_name having count(*)>1)c

Masum
  • 119
  • 11