CASE WHEN Statement referencing two different Columns - sql

As you can see in the screenshot below, there are multiple account numbers that have either a "successful" or "fail" outcome. Some account numbers have multiple entries like account_number "413655". For accounts like "413655", where one outcome is Success, and the other outcome is fail, I want to create a new column that shows "success" for both entries. Only accounts that have all fail outcomes should display "fail" in this new column "Distinct_count". The rest should display "success".
SCREENSHOT: https://i.stack.imgur.com/NQZmY.jpg
Please find my query below.(I have bolded the part that needs to be edited)
-- #WbResult v_tcci_collection_activity_fact
SELECT date_dim_id,
B.user_key,
B.product_type,
B.dealer_nbr,
(CASE B.make
WHEN 'TOYOTA' THEN 'TOYOTA'
WHEN 'SUBARU' THEN 'SUBARU'
WHEN 'LEXUS' THEN 'LEXUS'
ELSE 'OTHER'
END),
C.dealer_name,
C.zone,
activity_date,
activity_time,
activity_code,
(CASE WHEN len(b.loan_nbr) > 3
THEN b.loan_nbr
ELSE b.lease_nbr END)
AS account_number,
(CASE WHEN activity_code IN ('SHPS','SBPS','SOPS','SHCS','SBCS') THEN 'Successful'
ELSE 'Fail' END)
AS outcome,
**(CASE WHEN outcome = 'Successful' AND outcome = 'Fail' OR outcome = 'Successful' THEN 'Successful'
ELSE 'Fail' END)
AS distinct_count**
FROM dm_business_ops_tcci.v_tcci_collection_activity_fact A
left join dm_business_ops_tcci.v_tcci_collection_account_dim B
on A.collection_account_dim_id = B.collection_account_dim_id
left join dm_business_ops_tcci.v_tcci_dealer_dim C
on A.dealer_dim_id = C.dealer_dim_id
where activity_code IN ('SBCS','SOPF','SBPS','SOPS','SHPF','SHPS','SBCF','SBPF','SHCF','SHCS')

It's difficult to parse through the whole query in your example, but in your scenario a Windowing Function is a good way to achieve this scenario.
Your query won't work as it's only doing things row-by-row, so you need to be able to take in the details from the other row to make it happen.
In your case you want to use a Windowing Function like the following (simplified from your specific example):
MAX(outcome) OVER (PARTITION BY account_number) AS outcome_overall
Here I am being a little cheap and nothing that Successful comes after Fail in the dictionary to utilize MAX. But with this, outcome_overall is calculated by:
Partitioning the dataset into separate chunks based on account_number.
Within each partition, it finds the MAX(outcome).
outcome_overall is that value from #2, repeated for each row in that partition.
Example data and what outcome_overall would be:
account_number
outcome
outcome_overall
A1
Successful
Successful
A1
Fail
Successful
A2
Fail
Fail
A2
Fail
Fail
A3
Successful
Successful
A4
Fail
Fail

Related

Check data condition with multiple row and get only single output value

Check data condition with multiple row and get only single output value
Status
SUCCESSFULL
SUCCESSFULL
SUCCESSFULL
SUCCESSFULL
Then need Output "SUCCESSFULL"
IF any record have "Failed" status then output will be "Failed" as below
Status
SUCCESSFULL
SUCCESSFULL
FAILED
SUCCESSFULL
Then need Output "FAILED"
Are you merely looking for this:
select min(status) from mytable;
('FAILED' comes before 'SUCCESSFULL' in the alphabet, so with MIN you get 'FAILED' when at least one row is 'FAILED' and 'SUCCESSFULL' only if all rows are 'SUCCESSFULL'.)
You can use aggregation functions count() and sum() to achieve this.
select
case when
sum(case when status = 'SUCCESSFULL' then 1 else 0 end) = count(1)
then 'SUCCESSFULL'
else 'FAILED'
end
from tableA
SELECT DISTINCT Status
FROM Your_table
ORDER BY status

SQL: Select rows that contains at least two items and one other item

I need to verify that a list of information given to me contains the information that has at least two items - engine (starts with either 'E' or 'PE') - and one another item - chief unit (starts with 'BC').
My initial query was this and I need help modifying it to show me the correct data.
select distinct IncidentNum, Unit
from unit
where (unit like 'E%'
or unit like 'PE%'
or unit like 'BC%')
and unit not like 'EMS%'
and IncidentNum = '19-00001912'
group by incidentnum, unit
having count(*) > 2
You can use conditional aggregation to find the incidentnums that match the conditions:
select IncidentNum
from unit
group by IncidentNum
having sum(case when unit like 'E%' or unit like 'PE%' then 1 else 0 end) >= 2 and -- meets P/E condition
sum(case when unit like 'BC%' then 1 else 0 end) > 0 and -- meets BC condition
You can modify the having clause to get the inverse -- the ones that don't match both conditions (= 0 or = 0).
I do not know what these conditions are for:
unit not like 'EMS%'
IncidentNum = '19-00001912'
Because they are not part of your question.

SQL query question. Extracting data met for one of two conditions but not both

I'm extracting student data who have completed a list of courses for degree requirements. One of the courses on the list is equivalent to another course, so if a student completes both equivalent courses, it can only be counted once towards a degree. I need to extract data on students who completed the list of courses, while filtering for just one of the equivalent courses.
Where am I going wrong?
I've tried different OR and AND NOT clauses but I can't seem to get the result that I need
use coll18_live
select ENR_STUDENT_ID, ENR_TERM, CRS_NAME, ENR_GRADE
from dbo.CA320_ENROLLMENT_VIEW_N03
WHERE ENR_CENSUS_REG_FLAG = 'Y'
and ENR_TERM in ('14/FA', '15/SP')
and not (CRS_NAME = 'BUSI-105' and CRS_NAME = 'ENGL-120')
and CRS_NAME in ('ACCT-120', 'ACCT-125', 'BUSI-100', 'BUSI-103', 'BUSI-105', 'ENGL-120')
I expect the output to show students who completed ACCT-120, ACCT-12, BUSI-100, BUSI-103, and BUSI-105 or ENGL-120 (but not both BUSI-105 or ENGL-120)
I think you want aggregating with a having clause. You cannot do this with a WHERE, because the information you want is (apparently) in different rows:
select ENR_STUDENT_ID
from dbo.CA320_ENROLLMENT_VIEW_N03
where ENR_CENSUS_REG_FLAG = 'Y' AND
ENR_TERM in ('14/FA', '15/SP')
group by ENR_STUDENT_ID
having sum(case when CRS_NAME in ('ACCT-120', 'ACCT-125', 'BUSI-100', 'BUSI-103') then 1 else 0 end) = 4 and
sum(case when CRS_NAME in ('BUSI-105', 'ENGL-120') then 1 else 0 end) > 0;

SQLServer Creating a Case in a query based on top 100 results

I'm trying to create a SQL Server query based on the following criteria:
The query focuses on three columns: Report_Status, Error_Message, and Create_Date. The purpose of the query is to filter the top 100 most recent results based on the Create_Date. Once that's done, it needs to see if EVERY row in Report_Status in that top 100 says 'Failed' AND that Error_Message does not contain 'Placement is missing%'.
If it meets those conditions, then it needs to output the message "Potential service failure." If it doesn't meet those conditions, then it either needs to do nothing or output something normal, like "No problems found."
I figured a Case might be the best way to do this, so I tried it out. I'm having trouble getting it to work, though:
select Report_Status, Error_Message, Create_Date,
case
when Report_Status = 'Failed' and Error_Message not like 'Placement is missing%' then 'Potential service failure.'
ELSE 'No problems found.'
end
from [AUDIT_TABLE] limit 100
Is this the best way to approach this problem? If so, what do I need to change so this works? If it's not a good way, what's a better way to tackle the problem?
You would appear to want something like this:
select (case when count(*) = 100 then 'Potential service failure.'
else 'No problems found.'
end) as summary
from (select a.*
from [AUDIT_TABLE]
order by date desc
fetch first 100 rows only
) t100
where Report_Status = 'Failed' and
Error_Message not like 'Placement is missing%'
I ended up working with a coworker to solve this. Gordon Linoff's CASE section was great, but we changed how we searched for the most recent 100 records by also using the Report_ID field.
select
(case when count(*) = 100 then 'Potential failure.'
else 'No problems found.'
end) as Result
from Audit_Table
where Report_Status = 'fail'
and Error_Message not like 'Placement is missing%'
and Report_ID >= (select min(Report_ID) from (select top 100 * from Audit_Table order by Report_ID desc ) t100)

Multiple SQL Counts in with multiple criteria

I've been trying to optimise the way I retrieve data from my database for display on a "dashboard" type of page for software development
My database structure is as follows:
Requirements Table that contains all the various requirements with various fields, but importantly a REQ_ID as key.
Tasks Table that contains can contain multiple tasks with a TASK_ID, TASK_NAME (DEV, TEST OR RELEASE), TASK_STATUS (Not Started, Complete, Blocked), TASK_WINDOW (Week1, Week2, .. etc. when task was completed) and a link back to a requirement with REQ_I. For example, a requirement may have multiple dev tasks, test tasks and release tasks but for can only be dev complete if all the dev tasks related to a requirement is complete, otherwise it is incomplete
I would like to query these two tables to provide me a results set that contains individually the number DEV Complete, Test Complete and Release Complete requirements per DEV task window in a single query. I'm currently performing multiple query each containing subqueries and then aggregating the results with PHP, however this in total takes 15 sec to exec, Can anybody please help me in consolidating this into a single query>
SELECT r.REQ_ID,
SUM(CASE WHEN t.TASK_NAME = 'DEV' THEN 1 ELSE 0 END) AS DevComplete,
SUM(CASE WHEN t.TASK_NAME = 'TEST' THEN 1 ELSE 0 END) AS TestComplete,
SUM(CASE WHEN t.TASK_NAME = 'RELEASE' THEN 1 ELSE 0 END) AS ReleaseComplete
FROM Requirements r
INNER JOIN Tasks t
ON r.REQ_ID = t.REQ_ID
WHERE t.TASK_STATUS = 'Complete'
GROUP BY r.REQ_ID
I realize this is an old question but I ran a test with the following patterns:
Pattern 1:
SELECT
[Count1] = SUM(CASE WHEN ... THEN 1 ELSE 0 END),
[Count2] = SUM(CASE WHEN ... THEN 1 ELSE 0 END)
FROM
[Table]
GROUP BY
[Field]
Pattern 2:
SELECT
[COUNT1] = (SELECT COUNT(*) FROM [Table] WHERE ...),
[Count2] = (SELECT COUNT(*) FROM [Table] WHERE ...)
In my case, when running both queries, pattern 2 took 36 % of the time and pattern 1 took 64%. To me, pattern 1 looks more elegant, but it didn't perform nearly as well in my scenario.