SQL server Procedure modification required - sql

I have a stored procedure which produces output like:
Success Fail Progress
----------------------------
1 2 3
But I want the output to be:
Recieved Count
----------------
success 1
----------------
fail 2
----------------
progress 3
Please can someone help me get this output from my sql server.
The current SQL:
select
sum(case when status='AK' then 1 else 0 end) as 'SUCCESS',
sum(case when status='E' then 1 else 0 end) as 'FAILURE',
sum(case when status NOT IN('AK','E')then 1 else 0 end) as 'PENDING'
from t
where [rec_datetime] BETWEEN '2008-02-11' AND DATEADD(DAY,1,'2008-02-11')

You can use UNPIVOT to move columns to rows:
SELECT b.[Received], b.[Count]
FROM (SELECT[Success] = 1, [Fail] = 2, [Progress] = 3) a
UNPIVOT ([Count] FOR [Received] IN ([Success], [Fail], [Progress])) b
Output
Received Count
----------- -----------
Success 1
Fail 2
Progress 3

replace your select statement with
select 'Success' as Received, sum(case when status='AK' then 1 else 0 end) as [count]
from t where [rec_datetime] BETWEEN '2008-02-11' AND DATEADD(DAY,1,'2008-02-11')
union all
select 'Fail', sum(case when status='E' then 1 else 0 end)
from t where [rec_datetime] BETWEEN '2008-02-11' AND DATEADD(DAY,1,'2008-02-11')
union all
select 'Progress' , sum(case when status NOT IN('AK','E')then 1 else 0 end)
from t where [rec_datetime] BETWEEN '2008-02-11' AND DATEADD(DAY,1,'2008-02-11')

tough without seeing your code or your data, but something like this might work:
select 'success' As Recieved, Success As [Count] from mytable
union all
select 'fail', Fail from mytable
union all
select 'progress', Progress from mytable

Related

Distinct count of 2 variables in SQL Server

My table has columns id and status (failed, success) and status_id. Failure entries are redundant until a success reponse is saved. How to fetch distinct success and failure count failure attempts to be counted only once?
Query I tried:
select
sum(case when status_id in (1,2,3,4) then 1 else 0 end) as success,
sum(case when status_id in (5,6,7,8) then 1 else 0 end) as failed
from test
This query works but failed attempts are counted twice
id
status_id
status
123
5
failed
123
1
success
123
7
failed
123
5
failed
desired output success - 1 failure - 2
To count each success/fail only once, do select distinct in a derived table before aggregating:
select
sum(case when status_id in (1,2,3,4) then 1 else 0 end) as success,
sum(case when status_id in (5,6,7,8) then 1 else 0 end) as failed
from (select distinct status_id from test) dt
Counting the unique status_id's might work.
select
COUNT(DISTINCT case when status_id in (1,2,3,4) then status_id end) as success,
COUNT(DISTINCT case when status_id in (5,6,7,8) then status_id end) as failed
from test

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

COUNT with WHERE clause giving more rows than without WHERE clause

This may not be the right forum to ask this but I want to understand the logical error happening in my query.
I have wrote below query to understand how many users have delivered messages greater than sent messages(possibly an error in data capture, just wanted to assess it).
SELECT COUNT(DISTINCT user_id)
FROM wk_24_trigger
UNION
SELECT COUNT(DISTINCT user_id)
FROM (
SELECT *, (CASE WHEN delivered > 0 THEN 1 ELSE 0 END) as D,
(CASE WHEN sent > 0 THEN 1 ELSE 0 END) as S
FROM wk_24_trigger) t
WHERE t.D > t.s
The result which I got are as belows
_c0
1 1056840
2 1819729
I am not getting why row 2 > row 1.
Ideally even if for every entry Delivered > Sent then row 2 and row 1 should have been same
Are you sure that the first row is the result from the first query and the second one from the second query..??
It always need not be..
Try adding alias name after the count in each query and verify the result..
you can check below example as well..
WITH TEMP
AS(
SELECT 'A' USER_ID , 1 DELIVERED , NULL SENT FROM DUAL
UNION
SELECT 'B' ID , 10 A , 1 B FROM DUAL
UNION
SELECT 'C' ID , NULL A , 1 B FROM DUAL
UNION
SELECT 'D' ID , -1 A , 1 B FROM DUAL
)
SELECT COUNT(DISTINCT USER_ID), 'QUERY_1' QUERY
FROM TEMP
UNION
(SELECT COUNT(DISTINCT USER_ID), 'QUERY_2'
FROM (
SELECT USER_ID,DELIVERED,SENT,
(CASE
WHEN DELIVERED > 0 THEN
1
ELSE
0
END) D,
(CASE
WHEN SENT > 0 THEN
1
ELSE
0
END) S
FROM TEMP) T
WHERE T.D > T.S);
and system output is as below..
COUNT(DISTINCTUSER_ID) QUERY
1 1 QUERY_2
2 4 QUERY_1
the same could be your case as well..

Group by several columns with count on another column SQL Server

I'm using SQL SERVER 2012 and I'm struggling with this SQL statement. Basically I have this table
table
I want to group by Date, and Username, with a count on the status column, like below :
query result
How can I achieve this?
You can use an aggredated query with a few conditional SUMs.
SELECT
LastUpdate,
UpdatedBy as User,
SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END) as A
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) as C
SUM(CASE WHEN Status = 'D' THEN 1 ELSE 0 END) as D
SUM(CASE WHEN Status = 'Z' THEN 1 ELSE 0 END) as Z
SUM(CASE WHEN Status = 'X' THEN 1 ELSE 0 END) as X
FROM table
GROUP BY LastUpdate, UpdatedBy
ORDER BY LastUpdate, UpdatedBy
You can try using conditional aggregation
select LastUpdate,UpdatedBy,
count(case when Status='A' then UpdatedBy end) as 'A',
count(case when Status='C' then UpdatedBy end) as 'C',
count(case when Status='D' then UpdatedBy end) as 'D',
count(case when Status='Z' then UpdatedBy end) as 'Z',
count(case when Status='X' then UpdatedBy end) as 'X'
from tablename
group by LastUpdate,UpdatedBy
Ok I figured it out with help from the guys answers
SELECT
CAST(LastUpdate as DATE),
UserName,
SUM(CASE WHEN Status = 1 THEN 1 ELSE 0 END) as [Status_1],
SUM(CASE WHEN Status = 2 THEN 1 ELSE 0 END) as [Status_2],
SUM(CASE WHEN Status = 3 THEN 1 ELSE 0 END) as [Status_3]
FROM Table
WHERE LastUpdate BETWEEN '2018-11-30 10:013:44.080' AND '2018-12-30 10:013:44.080'
GROUP BY CAST(LastUpdate as DATE), UserName
ORDER BY CAST(LastUpdate as DATE)
This is a sample query where I'm looking for records between two dates. The problem I was having was in part due to filtering on datetime rather than date. The lastupdate column is a datetime so by casting to date it solved the issue

how to calculate the percentage ratio of two columns in sql server?

I have the following query which is supposed to return the number of passed and failed activities.
I'm stock at calculating the percentage ratio between the failed and passed activities for each row, as you can see right now I am returning 0.
any help is much appreciated.
query:
WITH CTE
AS(
select activityid,
SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) AS Pass,
SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) AS Fail
from mytable
group by activityid
)
select activityid, pass, fail,
0 as passPercentage, 0 failPercentage
from cte
resultset:
activityid pass fail passPercentage failPercentage
1 26 22 0 0
2 23 29 0 0
Try this:
WITH CTE
AS(
select activityid,
SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) AS Pass,
SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) AS Fail
from mytable
group by activityid
)
select activityid, pass, fail,
pass*100.0/(pass + fail) as passPercentage,
fail*100.0/(pass + fail) as failPercentage
from cte
UPDATE
In case f you have empty activities.
WITH CTE
AS(
select activityid,
SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) AS Pass,
SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) AS Fail
from mytable
group by activityid
)
select activityid, pass, fail,
CASE WHEN pass + fail = 0 THEN 0 ELSE pass*100.0/(pass + fail) END as passPercentage,
CASE WHEN pass + fail = 0 THEN 0 ELSE fail*100.0/(pass + fail) END as failPercentage
from cte