SUM of grouped COUNT in SQL Query - sql

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?

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

SELECT name, COUNT(name) AS count, SUM(COUNT(name)) OVER() AS total_count
FROM Table GROUP BY name

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

Try this:
SELECT ISNULL(Name,'SUM'), count(*) as Count
FROM table_name
Group By Name
WITH ROLLUP

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 ;

Please run as below :
Select sum(count)
from (select Name,
count(Name) as Count
from YourTable
group by Name); -- 6

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

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

For Sql server you can try this one.
SELECT ISNULL([NAME],'SUM'),Count([NAME]) AS COUNT
FROM TABLENAME
GROUP BY [NAME] WITH CUBE

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

You can use ROLLUP
select nvl(name, 'SUM'), count(*)
from table
group by rollup(name)

Use it as
select Name, count(Name) as Count from YourTable
group by Name
union
Select 'SUM' , COUNT(Name) from YourTable

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

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`;

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

After the query, run below to get the total row count
select ##ROWCOUNT

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

Related

SUM UP two columns and then find the find MAX value in SQL Server

I am working with Microsoft SQL Server and want to find E_ID and E_Name where T1+T2 has the MAX value.
I have two steps to reach the necessary result:
Find the sum of two columns AS "total" in a table
Find the row that contains the maximum value from total
Table named "table1" looks like the following (T2 may contains NULL values):
E_ID
E_Name
T1
T2
1
Alice
55
50
2
Morgan
60
40
3
John
65
4
Monica
30
10
5
Jessica
25
6
Smith
20
5
Here is what I've tried:
SELECT
E_ID, E_Name, MAX(total) AS max_t
FROM
(SELECT
E_ID, E_Name, ISNULL(T1, 0) + ISNULL(T2, 0) AS total
FROM
table1) AS Q1;
I get this error:
'Q1.E_ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I get the result only when I keep MAX(total) AS max_t in the SELECT part but I also want to have the columns E_ID and E_Name.
Try this - just sort by the Total column in a descending fashion, and take the first row in the result:
SELECT TOP (1)
Q1.E_ID, Q1.E_Name, Q1.Total
FROM
(SELECT
E_ID, E_Name, ISNULL(T1, 0) + ISNULL(T2, 0) AS Total
FROM
table1) AS Q1
ORDER BY
Q1.Total DESC;
You can use the query:
SELECT top 1 E_ID, E_Name, (T1+T2) as Total
FROM Table1
GROUP BY E_ID,E_Name
ORDER BY Total desc
SELECT
TOP (1) , E_ID, E_Name, ISNULL(T1, 0) + ISNULL(T2,0) AS Total
FROM
table1
ORDER BY
Total DESC;
If you wanna see all the records you just need to apply the GROUP BY clause.
SELECT
E_ID
, E_Name
, MAX(total) AS max_t
FROM
(SELECT
E_ID
, E_Name
, ISNULL(T1, 0) + ISNULL(T2, 0) AS total
FROM
table1
) AS Q1
GROUP BY
E_ID
, E_Name;
If you want to see only the MAX value in the dataset you just need to apply the TOP 1 (for one record in the result), then sum the T1 and T2 as total and
then apply the ORDER BY DESC;
SELECT TOP 1
E_ID
, E_Name
, (T1 + T2) AS total
FROM
table1
ORDER BY
total DESC
You can do it without subqueries, by ordering purposefully your data:
SELECT TOP 1
E_Name
FROM tab
ORDER BY COALESCE(T1,0)+COALESCE(T2,0) DESC
Check the demo here.

SQL change the specific row

In my table below, i want to change the placement of specific row.
For example,
ID Name Count
1 X 50
2 Y 30
3 other 25
4 Z 20
It is DESC ordered and i would like to see X,Y,Z orderly. Also, in total, 'other' should be counted. In other words, count should be 125.
You can use union all and add last row to the end.
Something like this:
select id, name,count from table where name<>other
union all
select 4 as id, "other"as name, 135 as count from table
order by 1
or if you want to sum it
select id, name,count from table where name<>other
union all
select 4 as id, 'other' as name, sum(count) as count from table
order by 1
You can put some logic in the order by clause:
select id, name, count
from table
order by case when id <> 3 then 1 else 2 end, id
This way, the first ordering criteria is "rows X, Y, Z first, then the other ones", then you order the groups the way you want, in your case either by id or by name will work.
You can find a working example here
TRY THIS :
SELECT ID,
Name,
CASE
WHEN Name = 'OTHER' THEN (SELECT SUM (COUNT) FROM YOUR_TABLE)
ELSE SUM (COUNT)
END
FROM YOUR_TABLE
GROUP BY Name
ORDER BY Name DESC
I think union all may be the simplest approach, but like this:
select id, name, count
from ((select id, name, count, 1 as ord
from t
where name in ('X', 'Y', 'Z')
) union all
(select 4, 'other', sum(count), 2 as ord
from t
)
) t
order by ord, name;

How to filter max value records in SQL query

I want to get all records except max value records. Could you pls suggest query for that.
For eg,(Im taking AVG field to filter)
SNO Name AVG
1 AAA 85
2 BBB 90
3 CCC 75
The query needs to return only 1st and 3rd records.
Use the below query:
select * from tab where avg<(select max(avg) from tab);
You could use a ranking function like DENSE_RANK:
WITH CTE AS(
SELECT SNO, Name, AVG,
RN = DENSE_RANK() OVER (ORDER BY AVG DESC)
FROM dbo.TableName
)
SELECT * FROM CTE WHERE RN > 1
(if you are using SQL-Server >= 2005)
Demo
select * from Sample where avg not in (select max(avg) from sample);
I think this should do
Try this
SELECT SNO, Name, AVG
FROM TableName
WHERE AVG NOT IN (SELECT MAX(AVG)
FROM TableName )

Getting rows with duplicate column values

I tried this with solutions avaialble online, but none worked for me.
Table :
Id rank
1 100
1 100
2 75
2 45
3 50
3 50
I want Ids 1 and 3 returned, beacuse they have duplicates.
I tried something like
select * from A where rank in (
select rank from A group by rank having count(rank) > 1
This also returned ids without any duplicates. Please help.
Try this:
select id from table
group by id, rank
having count(*) > 1
select id, rank
from
(
select id, rank, count(*) cnt
from rank_tab
group by id, rank
having count(*) > 1
) t
This general idea should work:
SELECT id
FROM your_table
GROUP BY id
HAVING COUNT(*) > 1 AND COUNT(DISTINCT rank) = 1
In plain English: get every id that exists in multiple rows, but all these rows have the same value in rank.
If you want ids that have some duplicated ranks (but not necessarily all), something like this should work:
SELECT id
FROM your_table
GROUP BY id
HAVING COUNT(*) > COUNT(DISTINCT rank)

how to calculate count in sql?

I have the following table:
memberid
2
2
3
4
3
...and I want the following result:
memberid count
2 2
3 1 ---Edit by gbn: do you mean 2?
4 1
I was attempting to use:
SELECT MemberID,
COUNT(MemberID)
FROM YourTable
GROUP BY MemberID
...but now I want find which record which has maximum count. IE:
memberid count
2 2
SELECT memberid, COUNT(*) FROM TheTable GROUP BY memberid
Although, it won't work for your desired output because you have "memberid = 3" twice.
Edit: After late update to question...
SELECT TOP 1 WITH TIES --WITH TIES will pick up "joint top".
memberid, COUNT(*)
FROM
TheTable
GROUP BY
memberid
ORDER BY
COUNT(*) DESC
SELECT MemberID, COUNT(MemberID) FROM YourTable GROUP BY MemberID
What if there is a tie (or more) for the max? Do you want to display one or all?
This is how I would do this
SELECT memberid, COUNT(1)
FROM members
GROUP BY memberid
HAVING COUNT(1) = (
SELECT MAX(result.mem_count)
FROM (
SELECT memberid, COUNT(1) as mem_count
FROM members
GROUP BY memberid
) as result
)
I would love to see a more efficient approach though.
Do it like this:
SELECT memberid, COUNT(memberid) AS [count] FROM [Table] GROUP BY memberid
This should do the trick with no subselects required:
select top 1 memberid, COUNT(*) as counted
from members
group by memberid
order by counted desc
Can be done quite easy:
SELECT TOP 1 MemberId, COUNT(*) FROM YourTable GROUP BY MemberId ORDER By 2 DESC
I believe the original poster requested 2 result sets.
The only way I know of to get this (in SQL Server) is to dump the original records into a temp table and then do a SELECT and MAX on that. I do welcome an answer that requires less code!
-- Select records into a temp table
SELECT
Table1.MemberId
,CNT = COUNT(*)
INTO #Temp
FROM YourTable AS Table1
GROUP BY Table1.MemberId
ORDER BY Table1.MemberId
-- Get original records
SELECT * FROM #Temp
-- Get max. count record(s)
SELECT
Table1.MemberId
,Table1.CNT
FROM #Temp AS Table1
INNER JOIN (
SELECT CNT = MAX(CNT)
FROM #Temp
) AS Table2 ON Table2.CNT = Table1.CNT
-- Cleanup
DROP TABLE #Temp
How about this query:
SELECT TOP 1 MemberID,
COUNT(MemberID)
FROM YourTable
GROUP BY MemberID
ORDER by count(MemberID) desc
SELECT count(column_name)
FROM your_table;
You need to use a subselect:
SELECT MemberID, MAX(Count) FROM
(SELECT MemberID, COUNT(MemberID) Count FROM YourTable GROUP BY MemberID)
GROUP BY MemberID
The second group by is needed to return both, the count and the MemberID.