SELECT Region ,
flag ,
Name,
COUNT(ID) AS 'CountWithFlag'
FROM Table
GROUP BY flag
this query gives me the following results. I am grouping by flag and I am able to get the counts for English/non-English based on flag. I also want to display Total Counts of English and non-English adjacent to counts
OUTPUT:
Region Flag Name CountWithFlag
a 0 English 100
b 1 Non-English 200
c 0 English 100
d 1 Non-English 200
DESIRED OUTPUT:
Region Flag Name CountWithFlag Total
a 0 English 100 200
b 1 Non-English 200 400
c 0 English 100 200
d 1 Non-English 200 400
How can I do that? I want to apply group by for specific counts with flag. But I also want to get total counts in same query!
Any inputs on how I can do that?
Another way would be something like this:
;
WITH agg1
AS (
SELECT region,
flag,
name,
COUNT(id) AS 'CountWithFlag'
FROM [dbo].[t2]
GROUP BY region,
flag,
name
),
agg2
AS (
SELECT [name],
COUNT(id) AS CountByName
FROM [dbo].[t2]
GROUP BY [name]
)
SELECT [agg1].[region],
[agg1].[flag],
[agg1].[name],
[agg1].[CountWithFlag],
[agg2].[CountByName]
FROM [agg1]
INNER JOIN [agg2]
ON [agg2].[name] = [agg1].[name]
try this
;
WITH cte
AS ( SELECT DISTINCT
Region ,
flag ,
Name ,
COUNT(ID) OVER ( PARTITION BY flag, Region, Name ) AS [CountWithFlag]
FROM [Table]
)
SELECT Region ,
flag ,
Name ,
SUM([CountWithFlag]) OVER ( PARTITION BY Name ) AS Total
FROM cte
If you want to avoid using window functions, you can do that:
SELECT
Region,
flag,
Name,
COUNT(ID) AS CountWithFlag,
(select count(ID) from Table as tbl1 where tbl1.Name=tbl.Name) AS Total
from Table as tbl
group by Region, flag, Name
But my opinion is that window aggregation should work much faster.
If you want use window aggregation then do this:
select
Region,
flag,
Name,
CountWithFlag,
sum(CountWithFlag) over(partition by Name) as Total
from (
SELECT
Region,
flag,
Name,
COUNT(ID) AS CountWithFlag
from Table as tbl
group by Region, flag, Name
) as tbl
Related
I have a table with 2 columns:
ID Status
-- -------
1 OK
2 OK
3 NOTOK
4 NOTOK
5 OK
I want to do a count and group by status and also have the sum of the count on each row. The count works but I do not know how to do the sum to appear on each row like this:
Status Count TotalCount
------- ----- ------
OK 3 5
NOTOK 2 5
SELECT COUNT(*) AS Count, SUM(*) AS Sum FROM *your table* GROUP BY Status.
You can use AS to rename whatever you want. I think sum will appear now.
select distinct Status, count(*) occurrences, count(*) over(partition by Status) total_count from table group by Status
You can use two windowed counts:
select distinct status,
Count(*) over(partition by status) as "count",
Count(*) over() as "Sum"
from t;
without window functions you could take various approaches, one would be
with c as (
select status, Count(*) as "Count"
from t
group by status
)
select *, (select Sum("count") from c) as "Sum"
from c
And in case CTE's are not supported...
select *, (select Count(*) from t) as "Sum"
from (
select status, Count(*) as "Count"
from t
group by status
)c
Use a subquery.
SELECT Status, COUNT(*) as Count, (SELECT COUNT(*) FROM my_table) AS TotalCount FROM my_table GROUP BY Status;
SQL Fiddle
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;
I have a code where I need to pull 400 random employees from this list of over 60,000. THere are 8 different job groupings, I need a certain number of each from each grouping. So of the total 400 random samples I need that 400 needs to consist of specific numbers from each of the 8 groups. This is the code so far:
SELECT TOP (400) Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
FROM dbo.v_TMS_employee_HR
ORDER BY NEWID()
IE: Of the 400 random records returned: Group 1 needs to have 45, Group 2 needs 50, Group 3 needs 35, Group 4, needs 25, Group 5 needs 100, Group 6 needs 5, Group 7 needs 70 and Group 8 needs 70.
And each group is made up of 1-4 different job codes.
If it's just 8 groups you can have 8 separate queries (1 for each group) with their own TOP number and then UNION them all together.
Something like this (You will need to set the correct record amounts to get for each group and correct group codes):
SELECT * FROM
(SELECT TOP (100) Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
FROM dbo.v_TMS_employee_HR
WHERE Job_Group_Code=1
ORDER BY NEWID())
UNION
...................
UNION
...................
...................
UNION
SELECT * FROM (
SELECT TOP (10) Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
FROM dbo.v_TMS_employee_HR
WHERE Job_Group_Code=8
ORDER BY NEWID())
Since you clarified that there are several job_group_codes in a group you will need to use WHERE Job_Group_Code IN (1,2,3) instead.
If you have just 8 group and it's one time thing, please try #PM 77-1 suggested. However, I would use UNION ALL instead UNION.
If you have more group or number of records selected from each group are different, you may try the following way
DECLARE #GroupSelect TABLE (Job_Group_Code INT, NumberOfRecord INT)
INSERT INTO #GroupSelect VALUES (1 ,45), (2 ,50) , .... -- List all your group and number of records your want select from them
;WITH tbl AS (
SELECT Business_Unit, GEMSID, First_Name, Last_Name, Region, District, Job_Function, Email_Address, Job_Group_Code
, ROW_NUMBER() OVER (PARTITION BY Job_Group_Code ORDER BY NEWID()) as RowNo
FROM dbo.v_TMS_employee_HR
)
, numbers (
-- if you don't have number table, you may use this.
select number + 1 as number from master..spt_values WHERE type = 'P'
)
SELECT t.*
from tbl t
INNER JOIN #GroupSelect sg
ON sg.Job_Group_Code = t.Job_Group_Code
INNER JOIN numbers n
ON sg.NumberOfRecord >= n.number
WHERE n.number = t.RowNo
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
I have the following query that retrieve the number of users per country;
SELECT C.CountryID AS CountryID,
C.CountryName AS Country,
Count(FirstName) AS Origin
FROM Users AS U
INNER JOIN Country AS C ON C.CountryID = U.CountryOfOrgin
GROUP BY CASE C.CountryName,
C.CountryID
What I need is a way to get the top 10 and then sum all other users in a single row. I know how to get the top 10 but I`m stuck on getting the remaining in a single row. Is there a simple way to do it?
For example if the above query returns 17 records the top ten are displayed and a sum of the users from the 7 remaining country should appear on row 11. On that row 11 the countryid would be 0 and countryname Others
Thanks for your help!
You did not specify how you are ranking the top 10 so I'm assuming the highest counts are ranked higher?
With TopItems As
(
SELECT C.CountryID AS CountryID
, C.CountryName AS Country
, Count(FirstName) AS Origin
, ROW_NUMBER() OVER( ORDER BY Count(FirstName) DESC ) As Num
FROM Users AS U
JOIN Country AS C
ON C.CountryID = U.CountryOfOrgin
GROUP BY C.CountryName, C.CountryID
)
Select CountryId, Country, Origin
From TopItems
Where Num <= 10
Union ALL
Select 0, 'Others', Sum(Origin)
From TopItems
Where Num > 10
Something like this:
SELECT
-- show them
ROW_NUMBER() OVER (ORDER BY CASE WHEN country_code = 'Others' THEN 1 ELSE 0 END, SUM(n) DESC) AS nr,
countryID,
SUM(n)
FROM (
-- change name for some countries
SELECT
CASE WHEN nr >= 11 THEN 'Others' ELSE countryID END AS countryID,
n
-- select all countries
FROM (
SELECT
-- store number to recognize position
ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC) AS nr,
countries.countryID,
COUNT(*) AS n
FROM
countries WITH (NOLOCK)
JOIN
users WITH (NOLOCK)
ON
users.countryID = countries.countryID
GROUP BY
countries.countryID
) AS x
) AS y
GROUP BY
countryID
ORDER BY
-- show Others as last one
CASE WHEN countryID = 'Others' THEN 1 ELSE 0 END,
SUM(n) DESC
works for me.