Get result in single row - sql

I am querying on table below.
SELECT [RiskUniqueIdentificationNo]
,Count(*) AS TotalNoOfTasks
,[Status]
FROM [dbo].[Tasks]
GROUP BY [RiskUniqueIdentificationNo]
,[Status]
and here is my result set
but problem is that i want to get result for each [RiskUniqueIdentificationNo] in following way
| RiskUniqueIdentificationNo | | TotalNoOfTasks | | InProgressTask | | ClosedTask |
------------ ------------ ------------ ------------------------- ------------------
| 1 | | 3 | | 2 | | 1|
i have tried to do some thing like this
SELECT [RiskUniqueIdentificationNo]
,Count(*) AS TotalNoOfTasks
,CASE
WHEN [Status] = 'Closed'
THEN COUNT([Status])
ELSE 0
END AS ClosedTasks
,CASE
WHEN [Status] != 'Closed'
AND [EndDate] < GETDATE()
THEN COUNT([Status])
ELSE 0
END AS OverdueTasks
FROM [dbo].[Tasks]
GROUP BY [RiskUniqueIdentificationNo]
,[Status]
but can't succeeded. I need help that how can i accomplish this.

Remove status from GROUP BY and do a COUNT using CASE.
SELECT [RiskUniqueIdentificationNo],
COUNT(1) AS TotalNoOfTasks,
COUNT(CASE WHEN [Status]<> 'Closed' THEN 1 END) AS InProgressTask,
COUNT(CASE WHEN [Status]= 'Closed' THEN 1 END) AS ClosedTask
FROM [dbo].[Tasks]
GROUP BY [RiskUniqueIdentificationNo]

Move to conditional aggregation as below
Select [RiskUniqueIdentificationNo],
Count(*) as TotalNoOfTasks,
sum(case when [Status] = 'In progress' then 1 else 0 end) [InProgressTask],
sum(case when [Status] = 'Closed' then 1 else 0 end) [ClosedTask]
from [dbo].[Tasks]
group by [RiskUniqueIdentificationNo]

Related

USE ELSE 0 doesn't work as expected in SQL

I have the following SQL query:
SELECT
modal_text,
COUNT(CASE WHEN ab_group = "control" THEN 1 ELSE 0 END)
FROM
onboarding_modals
GROUP BY
1
ORDER BY
1;
This doesn't work as expected (it will count more than expected), but when I remove the ELSE 0 in aggregate function, it works as expected:
SELECT
modal_text, COUNT(CASE WHEN ab_group = "control" THEN 1 END)
FROM
onboarding_modals
GROUP BY
1
ORDER BY
1;
Could someone explain me why having the ELSE 0 will make it count more data than it should be?
*It will also work if I use ELSE NULL
Because a COUNT(SomeColumn) doesn't count the NULL's in a column.
COUNT(1) or COUNT(*) count the rows.
And so does a COUNT(CASE WHEN x=1 THEN 1 ELSE 0 END)
This has no NULL's to ignore, because it's either 1 or 0.
But a CASE WHEN x=1 THEN 1 END
is just the implicit shorter syntax for
CASE WHEN x=1 THEN 1 ELSE NULL END
So it's normal to COUNT without the ELSE.
COUNT(DISTINCT CASE WHEN x=1 THEN t.ID END)
If you do want to use an ELSE, then do it with a SUM
SUM(CASE WHEN x=1 THEN 1 ELSE 0 END)
Use SUM() instead of COUNT(), as in:
SELECT
modal_text,
SUM(CASE WHEN ab_group = "control" THEN 1 ELSE 0 END)
FROM
onboarding_modals
GROUP BY
1
ORDER BY
1;
Could someone explain me why having the ELSE 0 will make it count more data than it should be?
Becasue COUNT(CASE WHEN ab_group = "control" THEN 1 ELSE 0 END) is different to COUNT(CASE WHEN ab_group = "control" THEN 1 END) let's see a sample below
we can see there will be count when we use count(1) or count(0) except count(null) count function will not be count when the value is null
Query 1:
SELECT COUNT(1)
| COUNT(1) |
|----------|
| 1 |
SELECT COUNT(0)
| COUNT(0) |
|----------|
| 1 |
SELECT COUNT(NULL)
| COUNT(NULL) |
|-------------|
| 0 |
Query 2:
SELECT SUM(1)
| SUM(1) |
|--------|
| 1 |
SELECT SUM(0)
| SUM(0) |
|--------|
| 0 |
SELECT SUM(NULL)
| SUM(NULL) |
|-----------|
| (null) |
Results:

SQL - Trying to count records based on CASE WHEN (SIMPLE?)

Extremely simple case - I can't calculate properly the number of months for below table - the expected number is 2, not 3 - what is interesting the "valueagg" is calculated properly with same condition!
INSERT INTO ForgeRock
([productName], [description], [month], [value] )
VALUES
('OpenIDM', 'Y',1,33.2),
('OpenIDM', 'Y',2, 12.1),
('OpenIDM', 'Y',3, 1.1)
;
TEST
SELECT
productName,
description,
sum(CASE WHEN [MONTH] between 1 and 2 then [VALUE] else 0 end) valueagg --works
,count(CASE WHEN [MONTH] between 1 and 2 then [MONTH] else 0 end) month_count --doesn't work
,count(CASE WHEN [MONTH] between 1 and 2 then 1 else 0 end) month_count2 --doesn't work
FROM
ForgeRock
group by productName,
description
RESULT
| productName | description | valueagg | month_count | month_count2 |
|-------------|-------------|--------------------|-------------|--------------|
| OpenIDM | Y | 45.300000000000004 | 3 | 3 |
http://sqlfiddle.com/#!18/14603/3/0
You are using count() with else. count() counts the number of non-NULL values and -- 0 is just as "not NULL" as any other value.
Use sum() instead:
SELECT productName, description,
SUM(CASE WHEN [MONTH] between 1 and 2 then [VALUE] else 0 end) as valueagg --works
SUM(CASE WHEN [MONTH] between 1 and 2 then [MONTH] else 0 end) as month_count --doesn't work
SUM(CASE WHEN [MONTH] between 1 and 2 then 1 else 0 end) month_count2 --doesn't work
FROM ForgeRock
GROUP BY productName, description
Or remove the ELSE from the COUNT().
Remove the ELSE part of the CASE expressions:
SELECT
productName,
description,
sum(CASE WHEN [MONTH] between 1 and 2 then [VALUE] else 0 end) valueagg
,count(CASE WHEN [MONTH] between 1 and 2 then [MONTH] end) month_count
FROM
ForgeRock
group by productName,
description
or replace with SUM() like this:
SELECT
productName,
description,
sum(CASE WHEN [MONTH] between 1 and 2 then [VALUE] else 0 end) valueagg
,sum(CASE WHEN [MONTH] between 1 and 2 then 1 else 0 end) month_count
FROM
ForgeRock
group by productName,
description

Conditional count when case = 1, DB2

I'm currently trying to figure out the best way to do a conditional count as an alias in DB2 for Iseries. The below values represent job statuses where a job can be created, completed and cancelled so any one job will possibly have multiple status codes attached to it.
However, for my final value, I'm trying to get a count of jobs that only have the created status so that I can show how many are still open jobs. Basically looking for cases where the count for the created case = 1, but the below fails at the '='
SELECT
COUNT(CASE A1.JOB WHEN = 'CREATED' THEN 1 END) AS CREATED,
COUNT(CASE A1.JOB WHEN = 'CANCELLED' THEN 1 END) AS CANCELLED,
COUNT(CASE WHEN A1.JOB 'CREATED' = 1 then 1 END) AS OPEN
FROM SCHEMA.TABLE A1;
sample data and results:
Job ID | Status_code
-------------------------
123 'CREATED'
123 'COMPLETED'
521 'CREATED'
521 'CANCELLED'
645 'CREATED'
Results:
JOB | CREATED | CANCELLED | OPEN
-------------------------------------------
123 1 0 0
521 1 1 0
645 1 0 1
Assuming that the only "close" status is 'CANCELLED', you can use not exists like this:
select count(*)
from schema.table t
where t.status_code = 'CREATED' and
not exists (select 1
from schema.table t2
where t2.job = t.job and
t2.status_code in ('CANCELLED', 'COMPLETED', 'DELETED')
);
If you want multiple counts, then filtering like this does not work. So aggregate by job first:
select sum(is_created) as num_created,
sum(is_cancelled) as num_cancelled,
sum(is_created * (1 - is_cancelled) * (1 - is_completed) * (1 - is_deleted)) as open
from (select job,
max(case when status_code = 'CREATED' then 1 else 0 end) as is_created,
max(case when status_code = 'CANCELLED' then 1 else 0 end) as is_cancelled,
max(case when status_code = 'COMPLETED' then 1 else 0 end) as is_completed,
max(case when status_code = 'DELETED' then 1 else 0 end) as is_deleted
from t
group by job
) j
The following returns the result you need:
WITH TAB (Job_ID, JOB) AS
(
VALUES
(123, 'CREATED')
, (123, 'COMPLETED')
, (521, 'CREATED')
, (521, 'CANCELLED')
, (645, 'CREATED')
)
SELECT
Job_ID
, COUNT(CASE A1.JOB WHEN 'CREATED' THEN 1 END) AS CREATED
, COUNT(CASE A1.JOB WHEN 'CANCELLED' THEN 1 END) AS CANCELLED
, CASE
WHEN NULLIF(COUNT(1), 0) = COUNT(CASE A1.JOB WHEN 'CREATED' then 1 END)
THEN 1
ELSE 0
END AS OPEN
FROM TAB A1
GROUP BY JOB_ID;
With conditional aggregation:
SELECT
JobID,
MAX(CASE Status_code WHEN 'CREATED' THEN 1 ELSE 0 END) AS CREATED,
MAX(CASE Status_code WHEN 'CANCELLED' THEN 1 ELSE 0 END) AS CANCELLED,
MIN(CASE WHEN Status_code <> 'CREATED' THEN 0 ELSE 1 END) AS OPEN
FROM tablename
GROUP BY JobID
See the demo.
Results:
> JobID | CREATED | CANCELLED | OPEN
> ----: | ------: | --------: | ---:
> 123 | 1 | 0 | 0
> 521 | 1 | 1 | 0
> 645 | 1 | 0 | 1
Assuming valid close status is either "COMPLETED" or "CANCELLED", you can try following SQL.
SELECT
A1.JobID,
sum(CASE WHEN A1.Status_code = 'CREATED' THEN 1 ELSE 0 END) AS CREATED,
sum(CASE WHEN A1.Status_code = 'CANCELLED' THEN 1 ELSE 0 END) AS CANCELLED,
(
SUM(CASE WHEN A1.Status_code = 'CREATED' THEN 1 ELSE 0 END)
- sum(CASE WHEN A1.Status_code = 'CANCELLED' THEN 1 ELSE 0 END)
- sum(CASE WHEN A1.Status_code = 'COMPLETED' THEN 1 ELSE 0 END)
) AS OPEN
FROM SCHEMA.TABLE A1
GROUP BY A1.JobID

SQL separate the count of one column

I have a SQL table that contains three columns:
userId
userName
item
and I created this SQL query which will count all the items types of one user:
select
count(ItemID) as 'count of all items types',
userId,
userName
from
userTable
where
ItemID in (2, 3, 4)
and userId = 1
group by
userId, userName
The result will be like this:
+--------+----------+--------------------------+
| userId | userName | count of all items types |
+--------+----------+--------------------------+
| 1 | kim | 25 |
and I am looking for a way to separate the counting of itemes types, so the result should be like this:
+--------+----------+----------------+----------------+-----------------+
| userId | userName | count of item1 | count of item2 | count of item3 |
+--------+----------+----------------+----------------+-----------------+
| 1 | kim | 10 | 10 | 5 |
SELECT
userID,
userName,
SUM(CASE WHEN ItemID = 2 THEN 1 ELSE 0 END) AS count_of_item1,
SUM(CASE WHEN ItemID = 3 THEN 1 ELSE 0 END) AS count_of_item2,
SUM(CASE WHEN ItemID = 4 THEN 1 ELSE 0 END) AS count_of_item3
FROM
My_Table
GROUP BY
userID,
userName
This is called conditional aggregation. Use CASE for this.
With COUNT:
select
count(case when ItemID = 1 then 1 end) as count_item1,
count(case when ItemID = 2 then 1 end) as count_item2,
count(case when ItemID = 3 then 1 end) as count_item3
...
(then 1 could also be anything else except null, e.g. then 'count me'. This works because COUNT counts non-null values and when omitting the ELSE in CASE WHEN you get null. You could also explicitly add else null.)
Or with SUM:
select
sum(case when ItemID = 1 then 1 else 0 end) as count_item1,
sum(case when ItemID = 2 then 1 else 0 end) as count_item2,
sum(case when ItemID = 3 then 1 else 0 end) as count_item3
...
This is how you would do it :
select userId,
username,
SUM(CASE WHEN ItemID = '2' THEN 1 ELSE 0 END) AS Item2-Cnt,
SUM(CASE WHEN ItemID = '3' THEN 1 ELSE 0 END) AS Item3-Cnt,
SUM(CASE WHEN ItemID = '4' THEN 1 ELSE 0 END) AS Item4-Cnt
FROM userTable
GROUP BY userID, userName

SELECT DISTINCT HAVING Count unique conditions

I've searched for an answer on this but can't find quite how to get this distinct recordset based on a condition. I have a table with the following sample data:
+---------+-------------+
| Branch | Task Status |
+---------+-------------+
| Account | Completed |
| HR | Completed |
| Account | Completed |
| HR | Not Define |
| Account | Uncompleted |
| Account | Not Define |
| Account | Completed |
| HR | Uncompleted |
| HR | Uncompleted |
| HR | Completed |
| HR | Not Define |
+---------+-------------+
I'd like to create a query that shows the count of total task and also want total of Task Status wise numbers of tasks, e.g.
Branch Total Task Completed Uncompleted Not Define
Account 5 3 1 1
Admin 6 2 2 2
SELECT branch,
COUNT(*),
SUM(CASE status WHEN 'completed' THEN 1 END) AS completed,
SUM(CASE status WHEN 'uncompleted' THEN 1 END) AS uncompleted,
SUM(CASE status WHEN 'not define' THEN 1 END) AS not_define
FROM task
GROUP BY
branch
SELECT Branch
, COUNT(1) as Total
, COUNT(CASE WHEN TaskStatus = 'Completed' THEN 1 ELSE 0 END) AS Completed
, COUNT(CASE WHEN TaskStatus = 'Uncompleted' THEN 1 ELSE 0 END) AS Uncompleted
, COUNT(CASE WHEN TaskStatus = 'Not Define' THEN 1 ELSE 0 END) AS NotDefine
FROM Table
GROUP BY Branch
SELECT branch,
COUNT(*),
COUNT(CASE taskstatus WHEN 'Completed' THEN 1 END),
COUNT(CASE taskstatus WHEN 'Uncompleted' THEN 1 END),
COUNT(CASE taskstatus WHEN 'Not Define' THEN 1 END)
FROM YourTable
GROUP BY branch;
Try this
SELECT * FROM (SELECT
ROW_NUMBER() OVER(PARTITION BY Branch ORDER BY [Task Status]) AS No,
Branch,
sum (CASE WHEN [Task Status] = 'Completed' THEN 1 ELSE 0 END ) OVER (PARTITION BY Branch) AS [Completed],
sum (CASE WHEN [Task Status] = 'Not Define' THEN 1 ELSE 0 END ) OVER (PARTITION BY Branch) AS [Not Define],
sum (CASE WHEN [Task Status] = 'Uncompleted' THEN 1 ELSE 0 END ) OVER (PARTITION BY Branch) AS [Uncompleted]
FROM task ) AS T1 WHERE No = 1
or
SELECT * FROM (SELECT
ROW_NUMBER() OVER(PARTITION BY Branch ORDER BY [Task Status]) AS No,
Branch,
count (CASE WHEN [Task Status] = 'Completed' THEN 1 ELSE 0 END ) OVER (PARTITION BY Branch) AS [Completed],
count (CASE WHEN [Task Status] = 'Not Define' THEN 1 ELSE 0 END ) OVER (PARTITION BY Branch) AS [Not Define],
count (CASE WHEN [Task Status] = 'Uncompleted' THEN 1 ELSE 0 END ) OVER (PARTITION BY Branch) AS [Uncompleted]
FROM task ) AS T1 WHERE No = 1
In SQL Server2005+ you can use PIVOT operator
SELECT *
FROM (
SELECT *, COUNT(*) OVER(PARTITION BY Branch) AS TotalTask
FROM dbo.task
) p
PIVOT
(
COUNT(p.Task) FOR p.Task IN ([Completed], [Uncompleted], [Not Define])
) x
Demo on SQLFiddle