How to group and get count of rows based on value of one column in sql server - sql

I have a table of requests with columns RequestType,status .Status column values can be in-progress,complated etc.
I would like to get the list like
RequestType In-Progress Completed Total
Type1 10 5 15
Type2 10 10 20
I tried with group by using the 2 columns( RequestType,status) ,but it does not give me the exact result.
Please help me with the sql query.
Thanks in advance
Subin

One way to do it is using conditional aggrigation:
SELECT RequestType,
SUM(CASE WHEN Status = 'In-Progress' THEN 1 ELSE 0 END) As 'In-Progress',
SUM(CASE WHEN Status = 'Completed' THEN 1 ELSE 0 END) As 'Completed',
COUNT(Status) As 'Total'
FROM TableName
WHERE Status IN('In-Progress', 'Completed')
GROUP BY RequestType

Use PIVOT
select *, [In-Progress]+[Completed] total
from TableName
pivot ( count(status) for status in ([In-Progress], [Completed])) as p

Related

Calculate conversion rate with the specified conditions

Here is my sample data table:
ID
Status
1
New
1
Processed
2
New
2
Processed
3
New
3
Processed
4
Processed
5
New
What I am trying to solve here is calculate the conversion rate from Status 'New' to Status 'Processed'. From the dataset, only ID no.1,2 and 3 fulfilled the requirements of my problem, and ID no.4 and 5 do not have both stages. So by theory, the conversion rate should be 3/5 * 100% = 60%. How can I select the data in order to calculate the IDs that have both 'New' and 'Processed' status.
This is the code that I have tried but I know its wrong since it extracts all the IDs with no link between it.
SELECT 'Conversion rate from Assigned enquiry to In progess leads' as 'Name', round((a.processed / b.new),3) * 100 as 'Answer'
FROM
(
SELECT cast(count(ID)as float) as processed
from table1
WHERE STATUS_ID = 'Processed'
) as a
cross join
(
SELECT cast(count(ID)as float) as new
from table_1
WHERE STATUS_ID = 'NEW'
) as b
We can use conditional aggregation here:
WITH cte AS (
SELECT CASE WHEN COUNT(CASE WHEN Status = 'New' THEN 1 END) > 0 AND
COUNT(CASE WHEN Status = 'Processed' THEN 1 END) > 0
THEN 1 ELSE 0 END AS cnt
FROM yourTable
GROUP BY ID
)
SELECT 100.0 * SUM(cnt) / COUNT(*)
FROM cte;

SQL Multiple Rows to Single Row Multiple Columns

I am including a SQLFiddle to show as an example of where I am currently at. In the example image you can see that simply grouping you get up to two lines per user depending on their status and how many of those statuses they have.
http://sqlfiddle.com/#!3/9aa649/2
The way I want it to come out is to look like the image below. Having a single line per user with two totaling columns one for Fail Total and one for Pass Total. I have been able to come close but since BOB only has Fails and not Passes this query leaves BOB out of the results. which I want to show BOB as well with his 6 Fail and 0 Pass
select a.PersonID,a.Name,a.Totals as FailTotal,b.Totals as PassTotals from (
select PersonID,Name,Status, COUNT(*) as Totals from UserReport
where Status = 'Fail'
group by PersonID,Name,Status) a
join
(
select PersonID,Name,Status, COUNT(*) as Totals from UserReport
where Status = 'Pass'
group by PersonID,Name,Status) b
on a.PersonID=b.PersonID
The below picture is what I want it to look like. Here is another SQL Fiddle that shows the above query in action
http://sqlfiddle.com/#!3/9aa649/13
Use conditional aggregation if the number of values for status column is fixed.
Fiddle
select PersonID,Name,
sum(case when "status" = 'Fail' then 1 else 0 end) as failedtotal,
sum(case when "status" = 'Pass' then 1 else 0 end) as passedtotals
from UserReport
group by PersonID,Name
Use conditional aggregation:
select PersonID, Name,
sum(case when Status = 'Fail' then 1 else 0 end) as FailedTotal,
sum(case when Status = 'Pass' then 1 else 0 end) as PassedTotal
from UserReport
group by PersonID, Name;
With conditional aggregation:
select PersonID,
Name,
sum(case when Status = 'Fail' then 1 end) as Failed,
sum(case when Status = 'Passed' then 1 end) as Passed
from UserReport
group by PersonID, Name

calculating completed task ratio

I've a table with NAMES and STATUS with C(completed) and N(not completed) status. I want check how many tasks are not completed for each name. I tried the following code and it is returning all '0' values:
select name, (select count(status) from alteon where status= 'n') / (select count(status) from alteon) from alteon group by name;
I'm expecting the result as not completed / total assigned where total assigned = complete+not completed.
as mentioned earlier, I'm getting value as '0' beside each employee name.
I think the following query does what you want:
select name,
sum(case when status = 'n' then 1 else 0 end) as n_status,
avg(case when status = 'n' then 1.0 else 0 end) as n_status_ratio
from alteon;
Here is the query which gives the result as you explained above.
select count(status)as Total_assigned,
sum(IF(status='n', 1, 0)) as Not_completed,name
from alteon group by name ;
Here is the sqlfiddle
You don't have to use multiple select statements. Use CASE to count the incomplete tasks.
select name, count(case when status = 'n' then 1 else null end)/count(status)
from alteon
group by name;
sqlfiddle.

How to use subquery in sql server 2008?

I know this question might be repeated ... But I have query like this, I have a field "Compute_CRM_State" in my table. And that field contains data like "approved,pending,cancelled" but now i want to fetch total count of approved or pending or cancelled. I tried it with sub query. I can able to get total count of approved or pending or cancelled but.. I got same records many times.
query :
SELECT (SELECT COUNT(Compute_CRM_State) AS Expr1
FROM CRM_Doctor_Request
WHERE (CRM_State_Id = 1)) AS PENDING,
(SELECT COUNT(Compute_CRM_State) AS Expr2
FROM CRM_Doctor_Request AS CRM_Doctor_Request_3
WHERE (CRM_State_Id = 2)) AS Approved,
(SELECT COUNT(Compute_CRM_State) AS Expr3
FROM CRM_Doctor_Request AS CRM_Doctor_Request_2
WHERE (CRM_State_Id = 3)) AS CANCELLED
FROM CRM_Doctor_Request AS CRM_Doctor_Request_1
There should be display only 1 record of count.. but it is getting display the number of times that number of records in table contains.
The reason you were not getting the total count correctly and getting many records instead, is that the COUNTs are selected as a correlated subquery, so you will got the count for each record in the table.
To fix that you have to use the aggregate function in the outer query, not from the correlated subuery. And to get those total count for each status, use the CASE expression to do this like so:
SELECT
SUM(CASE WHEN CRM_State_Id = 1 THEN 1 ELSE 0 END) AS PENDING,
SUM(CASE WHEN CRM_State_Id = 2 THEN 1 ELSE 0 END) AS Approved,
SUM(CASE WHEN CRM_State_Id = 3 THEN 1 ELSE 0 END) AS CANCELLED
FROM CRM_Doctor_Request;
SQL Fiddle Demo
Or: you can use the PIVOT table operator to do the same thing:
SELECT
[1] AS PENDING,
[2] AS Approved,
[3] AS Cancelled
FROM
(
SELECT * FROM CRM_Doctor_Request
) AS t
PIVOT
(
COUNT(Compute_CRM_State)
FOR CRM_State_Id IN([1], [2], [3])
) AS p;
Like this.

SQL - Counting a column twice

I have a table that has a column called 'status'. This can be set to 0 or 1
Is it possible for me to count both the 0's and 1's in a single query?
Thanks in advance
James
Yes, just group on the value of status:
SELECT status, COUNT(*)
FROM yourtable
GROUP BY status
That will give you exactly two rows since the value can only be 0 or 1, and the COUNT(*) column will be the number of times each status value appears in the table.
SELECT SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) AS 'number of zeroes',
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS 'number of ones'
FROM yourtable;