I'm hoping that someone is willing to help. I'm new to SQL and struggling to get a simple query debugged.
I want to create a simple frequency table to see how many values are missing (i.e. = 00000000) for the ArrestDate field.
SELECT
CASE WHEN ArrestDate=00000000 THEN 'NO DATE' ELSE 'HAS DATE' END AS HasDate,
CASE WHEN ArrestDate=00000000 THEN 0 ELSE 1 END as nDate
FROM ARREST_INFO
--GROUP BY HasDate
--GROUP BY CASE WHEN ArrestDate=00000000 THEN 'NO DATE' ELSE 'HAS DATE' END
Lines 1-4 parse without errors (output below).
Line 5 returns: Invalid column name 'HasDate'.
Line 6 returns: 'ARREST_INFO.ArrestDate' is invalid in the select
list because it is not contained in either an aggregate function or
the GROUP BY clause.
Since lines 1-4 run properly, I tried wrapping them inside another SELECT statement but this also elicits an error ("Invalid column name 'HasDate'.")
SELECT * FROM (
SELECT
CASE WHEN ArrestDate=00000000 THEN 'NO DATE' ELSE 'HAS DATE' END AS HasDate,
CASE WHEN ArrestDate=00000000 THEN 0 ELSE 1 END as nDate
FROM ARREST_INFO
)
GROUP BY HasDate
--GROUP BY CASE WHEN ArrestDate=00000000 THEN 'NO DATE' ELSE 'HAS DATE' END
Sadly, I can't update the SQL Server version. I'd be very grateful for any insight!
This answer to a previous question helped me figure out at least part of my problem. My Select statement referred to 2 columns, (nDate and HasDate), but my Group By statement only referred to one of them, so SQL didn't have enough information to determine how to display the unaggregated column data.
#Bill Karwin wrote:
https://stackoverflow.com/a/13999903/9499084
This demonstrates the single-value rule, which prohibits the undefined results you get when you run a GROUP BY query, and you include any columns in the select-list that are neither part of the grouping criteria, nor appear in aggregate functions (SUM, MIN, MAX, etc.).
I'm still not sure why SQL doesn't recognize the new column defined in the Select statement (HasDate) when it's redeployed in the Group By statement, but at least I have functioning code now -- see screenshot below for results.
Here's my updated code:
SELECT
CASE WHEN ArrestDate=00000000 THEN 'NO DATE' ELSE 'HAS DATE' END AS HasDate,
SUM(CASE WHEN ArrestDate=00000000 THEN 0 ELSE 1 END) AS nDate,
COUNT(*) as TotalCases
FROM ARREST_INFO
GROUP BY CASE WHEN ArrestDate=00000000 THEN 'NO DATE' ELSE 'HAS DATE' END
enter image description here
Related
I am trying to print all the patients and what illness name they suffer from. If a patient suffers from 'Love sickness' it is supposed to print 'Critical condition' next to it. How do I do this without altering the table?
This is what I have so far
SELECT patientName, illnessName
FROM Patient
JOIN Suffers ON Suffers.patientID = Patient.patientID
I was thinking I could use SELECT patientName, illnessName, 'Critical condition' AS condition but I don't know how to do that for specifically those with 'Love sickness'
Some help would be appreciated :)
It sounds like you just need to add a conditional piece of text to the illnessName. If that's the case the following should work:
SELECT p.patientName,
s.illnessName + case when s.illnessName='Love sickenss' then ' Critical condition' else '' end as illnessName
FROM Patient p
JOIN Suffers s ON s.patientID = p.patientID
Use case when to add 1 or multiple conditions.
In the example below i have added love sickness and one random value i.e sickness 2. If you have only one then you can remove it, but if you have more than 1 you can just add more when statement.
in the else statement you will have final condidion if you want. I passed a string value, but if you would want to ignore that then you can just doe else end
SELECT patientName,
illnessName,
case when illnessName = 'Love sickness' then 'Critical Condition'
when illnessName = ' sickness 2' then ' less critical'
........
else 'No illness condition specified' end as condition_level
FROM Patient
JOIN Suffers ON Suffers.patientID = Patient.patientID
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
I have a simple SQL query on IBM DB2. I'm trying to run something as below:
select case when a.custID = 42285 then 'Credit' when a.unitID <> '' then 'Sales' when a.unitID = '' then 'Refund'
else a.unitID end TYPE, sum(a.value) as Total from transactions a
group by a.custID, a.unitID
This query runs, however I have a problem with group by a.custID - I'd prefer not to have this, but the query won't run unless it's present. I'd want to run the group by function based on the result of the CASE function, not the condition pool behind it. So, I'm looking something like:
group by TYPE
However adding group by TYPE reports an error message "Column or global variable TYPE not found". Also removing a.custID from group section reports "Column custID or expression in SELECT list not valid"
Is this going to be possible at all or do I need to review my CASE function and avoid using the custID column since at the moment I'm getting a grouping also based on custID column, even though it's not present in SELECT.
I understand why the grouping works as it does, I'm just wondering if it's possible to get rid of the custID grouping, but still maintain it within CASE function.
If you want terseness of code, you could use a subquery here:
SELECT TYPE, SUM(value) AS Total
FROM
(
SELECT CASE WHEN a.custID = 42285 THEN 'Credit'
WHEN a.unitID <> '' THEN 'Sales'
WHEN a.unitID = '' THEN 'Refund'
ELSE a.unitID END TYPE,
value
FROM transactions a
) t
GROUP BY TYPE;
The alternative to this would be to just repeat the CASE expression in the GROUP BY clause, which is ugly, but should still work. Note that some databases (e.g. MySQL) have overloaded GROUP BY and do allow aliases to be used in at least some cases.
I am trying to create a new column "PolicyStatus" with a case statement. The the value of the case statement is dependent upon counting the number of occurrences of two variables and both of those variables have to occur a specific number of times.
Here is an example:
Grouping by OpportuntiyID, a policy is "Within Policy" if there are at least 3 QuoteID AND There are at least 3 Within7 that have a value of "Yes". Below is a sample data and my code thus far. Something is not going right with my case statement but I am not sure how to correct it.
The error that I am getting is:
Msg 102, Level 15, State 1, Line 35
Incorrect syntax near ')'.
This is referring to the case statement directly.
I thank you all in advanced for your assistance in correcting this.
OpportunityID,QUOTEID,DaysPassed,Within7
0060c00001QF5jiAAD,a060c00001REnnuAAD,-81,No
0060c00001QF5jiAAD,a060c00001REnpqAAD,-81,No
0060c00001QF5jiAAD,a060c00001REnsBAAT,-81,No
0060c00001QGz6JAAT,NULL,NULL,No
0060c00001QHxZhAAL,a060c00001cVlyzAAC,-32,No
0060c00001QHxZhAAL,a060c00001cVlzEAAS,-32,No
0060c00001QHxZhAAL,a060c00001cVm02AAC,-32,No
0060c00001QHxZhAAL,a060c00001cVm0bAAC,-32,No
0060c00001QHxZhAAL,a060c00001cUhzeAAC,0,Yes
0060c00001QIaK3AAL,a060c00001cV9YeAAK,4,Yes
0060c00001QIaK3AAL,a060c00001cV9YZAA0,4,Yes
0060c00001QIFfZAAX,a060c00001REtIEAA1,43,Yes
0060c00001QIk2UAAT,a060c00001cUYm9AAG,18,Yes
0060c00001QIk2UAAT,a060c00001cUYmEAAW,18,Yes
0060c00001QIk2UAAT,a060c00001cUYmTAAW,18,Yes
0060c00001QIwgaAAD,a060c00001cVMekAAG,0,Yes
0060c00001QIWoPAAX,a060c00001cW8eAAAS,-35,No
0060c00001QIYKbAAP,a060c00001cUYHkAAO,-65,No
0060c00001QIYKbAAP,a060c00001cUYKtAAO,-65,No
0060c00001QIYKbAAP,a060c00001RDzNYAA1,6,Yes
0060c00001QL7bkAAD,a060c00001cUQCmAAO,21,Yes
0060c00001QL7bkAAD,a060c00001cUQCXAA4,21,Yes
0060c00001QL7bkAAD,a060c00001cUQDkAAO,21,Yes
0060c00001QLWg6AAH,NULL,NULL,No
0060c00001QxJSgAAN,NULL,NULL,No
0060c00001QxOe4AAF,NULL,NULL,No
0060c00001Rae5dAAB,a060c00001cUvOLAA0,3,Yes
0060c00001Rb5RoAAJ,a060c00001cUWgEAAW,8,Yes
0060c00001Rb5RoAAJ,a060c00001cUWgJAAW,8,Yes
0060c00001Rb8wuAAB,a060c00001cUvEaAAK,-1,Yes
0060c00001Rb8wuAAB,a060c00001cUvEGAA0,-1,Yes
SELECT
[OPPORTUNITYID]
, COUNT([QUOTEID]) AS 'CountOfQuotes'
, CASE WHEN COUNT([QUOTEID]) >= 3 AND COUNT([WITHIN7] = 'YES') >=3 THEN 'Within Policy'
ELSE 'Breached Policy' END AS 'PolicyStatus'
FROM [DB].dbo.[TABLE]
GROUP BY [OPPORTUNITYID]
ORDER BY [OpportunityID]
GO
You need to do conditional aggregation on the WITHIN7 column, counting how many times 'YES' appears. One option is to count a CASE expression.
SELECT
[OPPORTUNITYID],
COUNT([QUOTEID]) AS [CountOfQuotes],
CASE WHEN COUNT([QUOTEID]) >= 3 AND
COUNT(CASE WHEN [WITHIN7] = 'YES' THEN 1 END) >= 3
THEN 'Within Policy'
ELSE 'Breached Policy' END AS [PolicyStatus]
FROM [DB].dbo.[TABLE]
GROUP BY [OPPORTUNITYID]
ORDER BY [OpportunityID];
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)