Distinct count of 2 variables in SQL Server - sql

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

Related

Keep the number of data records but the sum of two other Variables should be calculated

I have a table with Course-Participants, Course_Id and Status.
I want the number of records from Course-Participants to stay the same. But from the combination of Course_Id and Status it should show a total.
It should look like this:
And this is my attempt:
SELECT
[Course_Id]
,Sum(case when Course_ID is not null and Status = 0 THEN 1 else 0 end) as Sum_Status_A
,Sum(case when Course_ID is not null and Status = 1 THEN 1 else 0 end) as Sum_Status_B
,Sum(case when Course_ID is not null and Status = 2 THEN 1 else 0 end) as Sum_Status_C
FROM CourseParticipant
group by course_id
because of the group by statement, I cannot include the course participant in the query. As a result, I cannot output the desired number of data records.
Also select participant_id and add it the the group by:
SELECT
Course_Id,
Participant_id,
Sum(case when Course_ID is not null and Status = 0 THEN 1 else 0 end) as Sum_Status_A,
Sum(case when Course_ID is not null and Status = 1 THEN 1 else 0 end) as Sum_Status_B,
Sum(case when Course_ID is not null and Status = 2 THEN 1 else 0 end) as Sum_Status_C
FROM CourseParticipant
group by course_id, participant_id

SQL return only specific rows with specific status

I have this table below with two columns
Order_No Order_Status
A Receiving
A Active
A Retired
A Ordering
B Receiving
B Ordering
C Active
C Retired
D Receiving
E Ordering
I would like to get Order_no B, D and E records because it's order status is ( Receiving/Ordering ). It should filter out A and C because both have Active and Retired status.
I tried the below query but it's not showing up the results.
select ORDER_NUMBER
from table ror
where ror.use_Status
Order_Status not in ('Active', 'Retired')
and Order_Status in ('Receiving', 'Ordering').
Could anyone please tell me what wrong I am doing or I'm missing any joins?
You can use group by and having:
select order_no
from mytable
group by order_no
having max(case when status = 'Receiving' then 1 else 0 end) = 1
and max(case when status = 'Ordering' then 1 else 0 end) = 1
and max(case when status not in ('Receiving', 'Ordering') then 1 else 0 end) = 0
This phrases as: get all orders that have both "Receiving" and "Ordering" statuses, and no other status.
If a given order cannot have the same status twice, then the having can be simplified a little:
having sum(case when status in ('Receiving', 'Ordering') then 1 else 0 end) = 2
and sum(case when status not in ('Receiving', 'Ordering') then 1 else 0 end) = 0
Edit - if you want order that have either "Receiving" and "Ordering" statuses (not necessarily both), then a single condition is sufficient:
having max(case when status not in ('Receiving', 'Ordering') then 1 else 0 end) = 0

SQL Query to fetch employee Attendence

I need to write query on employee table to fetch the employee with employee ID & how many days he is present absent & half-day for given date range.
Employee
AID EmpID Status Date
1 10 Present 17-03-2015
2 10 Absent 18-03-2015
3 10 HalfDay 19-03-2015
4 10 Present 20-03-2015
5 11 Present 21-03-2015
6 11 Absent 22-03-2015
7 11 HalfDay 23-03-2015
Expected Output will be :
EmpID Present Absent HalfDay
10 2 1 1
11 1 1 1
Can you please help me with the Sql query ?
Here Is the query I tried
SELECT EMP.EMPID,
(CASE WHEN EMP.STATUS = 'Present' THEN COUNT(STATUS) ELSE 0 END) Pres,
(CASE WHEN EMP.STATUS = 'Absent' THEN COUNT(STATUS) ELSE 0 END) ABSENT,
(CASE WHEN emp.status = 'HalfDay' THEN Count(status) ELSE 0 END) HalfDay
FROM EMPLOYEE EMP GROUP BY emp.empid
The COUNT() function tests if the value is NOT NULL. Therefore it will always increment for both sides of a CASE statement like this:
COUNT(CASE Status WHEN 'Present' THEN 1 ELSE 0) AS Present
So we need to use SUM() ...
select empid,
sum(case when status='Present' then 1 else 0 end) present_tot,
sum(case when status='Absent' then 1 else 0 end) absent_tot,
sum(case when status='HalfDay' then 1 else 0 end) halfday_tot
from employee
group by empid
order by empid
/
... or use COUNT() with a NULL else clause. Both produce the same output, perhaps this one is clearer:
SQL> select empid,
2 count(case when status='Present' then 1 end) present_tot,
3 count(case when status='Absent' then 1 end) absent_tot,
4 count(case when status='HalfDay' then 1 end) halfday_tot
5 from employee
6 group by empid
7 order by empid
8 /
EMPID PRESENT_TOT ABSENT_TOT HALFDAY_TOT
---------- ----------- ---------- -----------
10 2 1 1
11 1 1 1
SQL>
Note that we need to use ORDER BY to guarantee the order of the result set. Oracle introduced a hashing optimization for aggregations in 10g which meant GROUP BY rarely returns a predictable sort order.
Replace 0 with null because it would be also come in count and added the where clause for date range, check the example below:
select empID,
count(case when status='Present' then 1 else null end) Present_Days,
count(case when status='Absent' then 1 else null end) Absent_Days,
count(case when status='HalfDay' then 1 else null end) HalfDays
from Employee
where date >= to_date('17mar2015') and date <= to_date('23mar2015')
group by empID

SQL: Comparing count of 2 fields with specific value

I have 2 tables, one (Jobs) contains the list of the jobs and second contains the details of the records in each job.
Jobs
JobID Count
A 2
B 3
Records
JobID RecordID ToBeProcessed IsProcessed
A A1 1 1
A A2 1 1
B B1 1 1
B B2 1 0
B B3 1 0
How would I be able to create a query that would list all the jobs that have the count of ToBeProcessed which has a value of 1 is equal to the count of isProcessed that has a value of 1? Thanks in advance. Any help is greatly appreciated.
Start with the calculation of the number of items with ToBeProcessed set to 1 or IsProcessed set to one:
SELECT
JobID
, SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END) ToBeProcessedIsOne
, SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END) IsProcessedIsOne
FROM Records
GROUP BY JobID
This gives you all counts, not only ones where ToBeProcessedIsOne is equal to IsProcessedIsOne. To make sure that you get only the records where the two are the same, use either a HAVING clause, or a nested subquery:
-- HAVING clause
SELECT
JobID
, SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END) ToBeProcessedIsOne
, SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END) IsProcessedIsOne
FROM Records
GROUP BY JobID
HAVING SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END)=SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END)
-- Nested subquery with a condition
SELECT * FROM (
SELECT
JobID
, SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END) ToBeProcessedIsOne
, SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END) IsProcessedIsOne
FROM Records
GROUP BY JobID
) WHERE ToBeProcessedIsOne = IsProcessedIsOne
Note: if ToBeProcessed and IsProcessed are of type that does not allow values other than zero or one, you can replace the CASE statement with the name of the column, for example:
SELECT
JobID
, SUM(ToBeProcessed) ToBeProcessedIsOne
, SUM(IsProcessed) IsProcessedIsOne
FROM Records
GROUP BY JobID
HAVING SUM(ToBeProcessed)=SUM(IsProcessedD)
if im not misunderstanding your question it looks like you just need a WHERE clause in your statement to see when they are both equal to 1.
SELECT
r.JobID AS j_id,
r.RecordID as r_id,
r.ToBeProcessed AS tbp,
r.IsProcessed AS ip
FROM Records AS r
WHERE r.ToBeProcessed = 1 AND r.IsProcessed = 1
GROUP BY j_id;
let me know if this is not what you are asking for.
if its a count from a different table then just do a count of the tbp and ip rows grouped by jobID and then the where should still do the trick

SQL server Procedure modification required

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