Select single value from same columns based on condition - sql

I have below table and using oracle sql
table name : TestCaseStatus
TestName Status TimeStamp
ABC Passed 11.10AM (Same Date)
ABC Failed 11.00 AM
ABC Failed 10.50 AM
EFG Passed 11.00AM
123 Failed 11.10 AM
123 Passed 11.00 AM
Result
TestName Status
ABC Passed_On_ReRun
123 Failed
EFG Passed
Question : Need query to get it. I have Tried MAX but not working

You can do this with window functions:
select
TestName,
case
when Status = 'Passed' and failed_once = 1
then 'Passed_On_Rerun'
else Status
end Status
from (
select
t.*,
rank() over(partition by TestName order by Timestamp desc) rn,
max(case when Status = 'Failed' then 1 else 0 end) over(partition by TestName) failed_once
from TestCaseStatus t
) t
where rn = 1
Demo on DB Fiddle:
TESTNAME | STATUS
:------- | :--------------
123 | Failed
ABC | Passed_On_Rerun
EFG | Passed

Assuming these are the only three conditions, you can use conditional aggregation:
select testname,
(case when max(timestamp) = max(case when status = 'Failed' then timestamp end)
then 'Failed'
when max(timestamp) = max(case when status = 'Passed' then timestamp end) and
sum(case when status = 'Failed' then 1 else 0 end) > 0
then 'Passed_On_Rerun'
when max(timestamp) = max(case when status = 'Passed' then timestamp end)
then 'Passed'
else '???'
end)
from TestCaseStatus tcs
group by testname;
In Oracle, you can simplify this to:
select testname,
(case when max(status) keep (dense_rank first order by timestamp desc) = 'Passed' and
sum(case when status = 'Failed' then 1 else 0 end) > 0
then 'Passed_On_Rerun'
else max(status) keep (dense_rank first order by timestamp desc)
end)
from TestCaseStatus tcs
group by testname;
Here is a db<>fiddle.
The keep syntax is getting the last value for the status based on the timestamp.

You may achieve what you want with the following query :
SELECT T1.TestName, T1.Status
FROM TestCaseStatus T1
WHERE T1.TimeStamp =
(SELECT MAX(T2.TimeStamp) FROM TestCaseStatus T2 WHERE T2.TestName = T1.TestName)
However, there is an issue with your sample data :
123 Failed 11.00 AM
123 Passed 11.00 AM
Same test is failed and passed for the same timestamp ?!
Edit : In order to achieve the 'Passed_On_ReRun' need, we could imagine a solution like this :
SELECT T1.TestName, IF(T1.count > 0 AND T1.Status = 'Passed', 'Passed_On_ReRun', T1.Status)
FROM
(SELECT T2.TestName
, T2.Status
, SUM(T2.Status = 'Failed') AS count
, MAX(T2.TimeStamp) AS TimeStamp
FROM TestCaseStatus T2
GROUP BY T2.TestName) T1

Related

Sort COUNT(CASE WHEN) results

I am taking a database of statuses and creating the statuses as columns in order to count how many records from a network exist in each status. I'd love to sort the results based on the Partnered column DESC, but I can't figure out how or where to do that??
Here's my code:
SELECT type,
COUNT(CASE WHEN status = "NOT_SUBMITTED" THEN storenumber END) AS Not_Submitted,
COUNT(CASE WHEN status = "PARTNERED" THEN storenumber END) AS Partnered,
COUNT(CASE WHEN status = "PENDING" THEN storenumber END) AS Pending,
COUNT(CASE WHEN status = "SUSPENDED" THEN storenumber END) AS Suspended,
COUNT(CASE WHEN status = "REJECTED" THEN storenumber END) AS Rejected,
FROM Programs
GROUP BY 1;
Here are my results so far.
row
type
Not_Submitted
Partnered
Pending
Suspended
Rejected
1
abc
26
473
36
0
374
2
def
2481
3943
797
363
1074
3
ghi
0
1965
0
150
102
4
jkl
1231
1851
0
0
0
You just add ORDER BY Partnered DESC as in below example
SELECT type,
COUNT(CASE WHEN status = "NOT_SUBMITTED" THEN storenumber END) AS Not_Submitted,
COUNT(CASE WHEN status = "PARTNERED" THEN storenumber END) AS Partnered,
COUNT(CASE WHEN status = "PENDING" THEN storenumber END) AS Pending,
COUNT(CASE WHEN status = "SUSPENDED" THEN storenumber END) AS Suspended,
COUNT(CASE WHEN status = "REJECTED" THEN storenumber END) AS Rejected,
FROM Programs
GROUP BY 1
ORDER BY Partnered DESC
Meantime, consider also below option
SELECT type,
COUNTIF(status = "NOT_SUBMITTED") AS Not_Submitted,
COUNTIF(status = "PARTNERED") AS Partnered,
COUNTIF(status = "PENDING") AS Pending,
COUNTIF(status = "SUSPENDED") AS Suspended,
COUNTIF(status = "REJECTED") AS Rejected,
FROM Programs
GROUP BY 1
ORDER BY Partnered DESC
and finally - try below one (it is my preferred option)
SELECT *
FROM (SELECT type, storenumber, status FROM Programs)
PIVOT (
COUNT(DISTINCT storenumber)
FOR status IN ("NOT_SUBMITTED", "PARTNERED", "PENDING", "SUSPENDED", "REJECTED")
)
ORDER BY PARTNERED DESC
Try this:
#standardSQL
WITH table as (
SELECT type,
COUNT(CASE WHEN status = "NOT_SUBMITTED" THEN storenumber END) AS Not_Submitted,
COUNT(CASE WHEN status = "PARTNERED" THEN storenumber END) AS Partnered,
COUNT(CASE WHEN status = "PENDING" THEN storenumber END) AS Pending,
COUNT(CASE WHEN status = "SUSPENDED" THEN storenumber END) AS Suspended,
COUNT(CASE WHEN status = "REJECTED" THEN storenumber END) AS Rejected,
FROM Programs
GROUP BY 1)
SELECT * FROM table ORDER BY Partnered DESC
I put your query in a subquery then querying the subquery to be ordered by Partnered DESC

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

Error in SQL command using Group by?

I'm beginner in Oracle SQL. I am using SQL Developer. This query is not executed. I need for each id like 1001,1002 how many no of yes status and how many no of no status. Thanks in advance....
I used this SQL:
SELECT ID, COUNT(STATUS)
FROM TABLE1
WHERE
GROUP BY ID, STATUS
HAVING STATUS = YES OR STATUS = NO;
I have table like this:
id school status
--------------------------
1001 vani YES
1002 sunbeam YES
1001 shristri YES
1002 jain NO
1001 holycross YES
1001 vani NO
I need output like
id yesstatus Nostatus
-------------------------
1001 3 1
1002 1 1
Your current query syntax is really wrong, but you can do conditional aggregation :
select id,
sum(case when status = 'YES' then 1 else 0 end) as yesstatus,
sum(case when status = 'NO' then 1 else 0 end) as Nostatus
from table1 t1
where status in ('YES', 'NO')
group by id;
select status, count(status)
from your_table
group by status
CREATE TABLE dbo.TABLE1
(
id INT,
school NVARCHAR(50) ,
status BIT
)
INSERT INTO dbo.TABLE1 ( id ,
school ,
status )
VALUES (1001,'vani',1),
(1002,'sunbeam', 1),
(1001,'shristri',1),
(1002,'jain',0),
(1001,'holycross',1),
(1001,'vani', 0)
SELECT id,
SUM(CASE WHEN status=1 THEN 1 ELSE 0 END) as yesstatus,
SUM(CASE WHEN status=0 THEN 1 ELSE 0 END) as Nostatus
FROM dbo.TABLE1
GROUP BY id

case statement for each row manipulations

Hi I have a table which has an ID and status.One ID can have multiple status but I have to pick status based on the conditions.
If ID 1 has Approved, Later,Modified I should Pick Approved and if the ID has only approved then Pick only Approved.But the case statement I got is not doing per ID.It is changing the overall data based on status.Please advise
select ID,
CASE
WHEN status = 'Approved'
AND status IN(
'Modified',
'Later'
) THEN 'Partial Modified'
WHEN status = 'Approved' THEN 'Approved'
when status IN('Modified','Edited') THEN 'Modified'
else status
END status group by ID,Status
This can be done with an ordering condition in row_number.
select top 1 with ties *
from tbl
order by row_number() over(partition by id order by case when status='Approved' then 1
when status='Modified' then 2
else 3 end)
I think you want an aggregation, so something like this:
(CASE WHEN SUM(CASE WHEN status = 'Approved' THEN 1 ELSE 0 END) > 0
THEN 'Approved'
WHEN SUM(CASE WHEN status = 'Modified' THEN 1 ELSE 0 END) > 0
THEN 'Modified'
ELSE MAX(status)
END)
Of course, you can also do this using window functions:
(CASE WHEN SUM(CASE WHEN status = 'Approved' THEN 1 ELSE 0 END) OVER (PARTITION BY id) > 0
THEN 'Approved'
WHEN SUM(CASE WHEN status = 'Modified' THEN 1 ELSE 0 END) OVER (PARTITION BY id) > 0
THEN 'Modified'
ELSE MAX(status) OVER (PARTITION BY id)
END)

How to save the switch cases results in different columns

I have the following query currently:
SELECT name, id,
CASE
WHEN( status = 'Missing' AND severity = 'Optional' ) AND ( id=123 )
THEN COALESCE(count(patchid),0)
ELSE 0
END AS missingoptional,
CASE
WHEN( status = 'Missing' AND severity = 'Important' ) AND ( id=123 )
THEN COALESCE(count(patchid),0)
ELSE 0
END as missingimportant
FROM tablename
GROUP BY name, id, status, severity
ORDER BY id
Current result:
name id missingoptional missingimportant
abc 123 10 0
abc 123 0 20
Expected result:
name id missingoptional missingimportant
abc 123 10 20
Please let me know what changes do I have to do in the above query to get the expected output.
Perhaps this is what you want:
SELECT name, id,
SUM(CASE
WHEN( status = 'Missing' AND severity = 'Optional' ) AND ( id=123 )
THEN 1
ELSE 0
END) AS missingoptional,
SUM(CASE
WHEN( status = 'Missing' AND severity = 'Important' ) AND ( id=123 )
THEN 1
ELSE 0
END) as missingimportant
FROM tablename
GROUP BY name, id
ORDER BY id
I removed status and severity from the GROUP BY, and instead put SUM() in the select-list to do aggregation.
Use MAX() aggregate function
SELECT name, id,
MAX(CASE
WHEN( status = 'Missing' AND severity = 'Optional' ) AND ( id=123 )
THEN COALESCE(count(patchid),0)
ELSE 0
END) AS missingoptional,
MAX(CASE
WHEN( status = 'Missing' AND severity = 'Important' ) AND ( id=123 )
THEN COALESCE(count(patchid),0)
ELSE 0
END) as missingimportant
FROM tablename
GROUP BY name, id
ORDER BY id