Using Case Statement to show yes or no - ssms

I am writing a code that looks at a program where you can enter tasks for certain jobs. Basically, I want the code to look at the program, and if there is a task that includes "TCU" it would flag it as yes. If that particular job doesn't have a task with "TCU" then flag it no.
This is the code I have, but it is returning "No" for everything even though I know there are tasks for all of these jobs.
SELECT wip.FinalAssemblyJobNumber
,fa.SCHEDULE_GROUP_NAME
,wip.StabilityDate
,CASE
WHEN fs.Task = '%TCU%'
THEN 'YES'
ELSE 'NO'
END AS FS_Status
FROM FINAL_ASSEMBLY_WIP_VIEWER_037.dbo.FinalAssemblyWIP wip
JOIN PIT.pub.FA_JOB fa ON fa.DISCRETE_JOB = wip.FinalAssemblyJobNumber
LEFT JOIN FLOOR_SUPPORT_037.dbo.FloorSupport fs ON fs.JobNumber = fa.DISCRETE_JOB AND fs.Closed =
1 AND fs.Task LIKE '%TCU%'
JOIN pit.mat.MTL_RQMTS AS mr ON mr.WIP_ENTITY_ID = fa.WIP_ENTITY_ID AND mr.ORGANIZATION_ID =
fa.ORGANIZATION_ID
JOIN pit.pub.ITEM_ACTIVE AS ia ON ia.INVENTORY_ITEM_ID = mr.INVENTORY_ITEM_ID AND
ia.ORGANIZATION_ID = mr.ORGANIZATION_ID
WHERE
wip.Stage1Date < getdate()
AND wip.StabilityDate IS NOT NULL
AND wip.AuthorizedDate IS NULL
AND ia.part_number = '991044688-'
AND fs.JobNumber IS NULL
AND wip.OracleCompletionDate IS NULL
ORDER BY wip.StabilityDate

In your CASE WHEN statement, you should use a LIKE instead of =, not sure if that will fix your problem though because your query is quite beefy, but you can't use = on a "%TCU%" comparison

Related

using case statement in a where clause

Hello I am missing something because my code errors.
select * from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where (ScheduleDate = testdate)
and
(Case
when HF.IsHoliday = 1 then (overtime = 1 and makeup = 0)
else
(overtime = 0 and Makeup = 0)
end
)
and
DOW = 5
order by ActivityStartTime
I've attempted several combinations and each one errors at either the first equal sign or the second. What am I missing?
The branches of a case expression can only return values, not additional expressions to be evaluated in the where condition. You could, however, simulate this behavior with the and and or logical operators:
select *
from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where (ScheduleDate = testdate) and
((HF.IsHoliday = 1 and overtime = 1 and makeup = 0) or
(overtime = 0 and Makeup = 0)) and
DOW = 5
order by ActivityStartTime
Note that you have makeup = 0 on both branches of the case expression in the question (or both sides of the or in the answer), so you could extract it out of it and simplify the condition a bit:
select *
from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where ScheduleDate = testdate and
makeup = 0 and
((HF.IsHoliday = 1 and overtime = 1) or
overtime = 0) and
DOW = 5
order by ActivityStartTime
If you are still wanting to know how to utilize a CASE Statement Expression in a WHERE Clause the CASE Expression must be compared to a value as that is the syntax understood for conditions contained within a WHERE Clause. See below a mock example.
SELECT *
FROM ##ScheduleDetail SD
LEFT JOIN ##HolidayFilterTbl HF ON SD.Scheduledate = HF.Testdate
WHERE(ScheduleDate = testdate)
AND
/* If you wish to stick with using a CASE Expression within the WHERE Clause set the the CASE Expression equal to 'something'. I usually stick with 1 or 0 'true/false'.
| You simply have to create your own True/False evaluation. You can add your logic checks within a CASE Expression within
| the WHERE Clause and when your logic is TRUE THEN return 1. Basically you are saying when 1 = 1 then return Record.
*/
1 =
Case
WHEN HF.IsHoliday = 1 AND makeup = 0 THEN
CASE WHEN (overtime = 1 OR overtime = 0) THEN 1 END /* Return 1 here to evaluation to TRUE */
ELSE
0 /* You can add another CASE here if needed and when the condition you write in evaluations to 1 'true' return record */
END
AND
DOW = 5
ORDER BY ActivityStartTime;
There are a few reasons I've used CASE Expressions within a WHERE Clause over using AND/ORs. Just one minor reason is it allows me to contain and organize logic in a WHERE Clause inside CASE Expressions rather than having multiple AND/ORs all nested together. I've also found that using CASE Expressions in the WHERE Clause is useful when encountering Dynamic queries that accept variables to be later inserted into the SQL before being sent to the database for processing. In the case of using Dynamic SQL there are times when a CASE Statement MUST be used due to the fact that there could be data that is being compared against in the WHERE clause that is NOT a column.field value but a hardcoded value that is compared to perhaps a user selection or status (as examples)... it might be a static value passed in via the application which is how my web application works that I support which is why I bring it up.
Basically it's good to know how to use a CASE Expression in a WHERE Clause as there are some cases when the ONLY way to evaluate certain data is by using a CASE Expression .
I have no data to test this against and that's not the point. The point of my answer is to simply provide to you an alternative to the existing answer. In my opinion this logic is basic and the already provided answer is the correct one however my answer is to demonstrate how you could go about using a CASE in a WHERE Clause.
If interested see this SO Post for the differences between a CASE Statement vs a CASE Expression however know that this terminology slightly differs between databases.
As an example of this... SQL Server refers to these as Simple vs Searched but refers to all of it as a CASE Expression. Therefore a CASE Expression can either be a Simple or a Searched CASE that can be used within a Statement.

SQL query to filter by specific date criteria

SQL query to filter by specific date criteria
SQL Server Management Studio V17.7
Question: I am looking for guidance related to a view on how to select records where the Start_Date falls between a defined date range when either the Admit_Status = 1 or Admit_Status = 0 as shown below:
Criteria should be something like: if admit status = 1 then dbo.PT_ASSIGNMENT.START_DATE >= referral_date to ifnull dbo.PT_ADMISSION.TERMINATION_DATE then now() else dbo.PT_ADMISSION.TERMINATION_DATE or if admit status = 0 then start_date >= referral_date to ifnull dbo.PT_ADMISSION.PROSPECT_TERM_DATE then now() else dbo.PT_ADMISSION.PROSPECT_TERM_DATE
My SQL query (View) excluding the above question:
SELECT dbo.RES_BASIC.RESOURCE_ID,
dbo.PT_ADMISSION.ADMISSION_ID,
dbo.PT_ASSIGNMENT.START_DATE,
(CASE PT_ADMISSION.PROSPECT_ADMIT_DATE WHEN NULL THEN PT_ADMISSION.ADMIT_DATE ELSE PT_ADMISSION.PROSPECT_ADMIT_DATE END) AS REFERRAL_DATE,
dbo.PT_ADMISSION.ADMIT_DATE,
dbo.PT_ADMISSION.PROSPECT_ADMIT_DATE,
dbo.PT_ADMISSION.PROSPECT_TERM_DATE,
dbo.PT_ADMISSION.TERMINATION_DATE,
CASE WHEN PT_ADMISSION.ADMIT_DATE IS NOT NULL THEN 1 ELSE 0 END AS ADMIT_STATUS,
dbo.PT_BASIC.PATIENT_CODE,
dbo.RES_BASIC.NAME_FULL
FROM dbo.PT_BASIC
INNER JOIN dbo.PT_STATUS
ON dbo.PT_BASIC.PATIENT_ID = dbo.PT_STATUS.PATIENT_ID
INNER JOIN dbo.A_PATIENT_STATUS
ON dbo.PT_STATUS.ADMIN_SET_ID = dbo.A_PATIENT_STATUS.ADMIN_SET_ID
AND dbo.PT_STATUS.STATUS_CODE = dbo.A_PATIENT_STATUS.STATUS_CODE
INNER JOIN dbo.O_DATASET
ON dbo.PT_BASIC.DATASET_ID = dbo.O_DATASET.DATASET_ID
INNER JOIN dbo.PT_ADMISSION
ON dbo.PT_BASIC.PATIENT_ID = dbo.PT_ADMISSION.PATIENT_ID
AND dbo.PT_STATUS.ADMISSION_ID = dbo.PT_ADMISSION.ADMISSION_ID
INNER JOIN dbo.PT_ASSIGNMENT
ON dbo.PT_BASIC.PATIENT_ID = dbo.PT_ASSIGNMENT.PATIENT_ID
INNER JOIN dbo.A_ASSIGNMENT_TYPE
ON dbo.PT_ASSIGNMENT.ADMIN_SET_ID = dbo.A_ASSIGNMENT_TYPE.ADMIN_SET_ID
AND dbo.PT_ASSIGNMENT.ASSIGNMENT_TYPE = dbo.A_ASSIGNMENT_TYPE.TYPE_ID
INNER JOIN dbo.RES_BASIC
ON dbo.PT_ASSIGNMENT.RESOURCE_ID = dbo.RES_BASIC.RESOURCE_ID
WHERE (dbo.O_DATASET.DATASET_NAME = 'XXXXXXXXXX')
AND (dbo.A_ASSIGNMENT_TYPE.DESCRIPTION = 'REFERRING PHYSICIAN')
GROUP BY dbo.RES_BASIC.NAME_FIRST + ' ' + dbo.RES_BASIC.NAME_LAST,
dbo.RES_BASIC.RESOURCE_ID,
dbo.PT_ADMISSION.ADMISSION_ID,
dbo.PT_BASIC.PATIENT_CODE,
dbo.PT_ASSIGNMENT.START_DATE,
dbo.PT_ADMISSION.PROSPECT_TERM_DATE,
dbo.PT_ADMISSION.PROSPECT_ADMIT_DATE,
dbo.PT_ADMISSION.TERMINATION_DATE,
dbo.PT_ADMISSION.ADMIT_DATE,
dbo.RES_BASIC.NAME_FULL
You can put pretty much any "if" into a condition with simple AND and OR use.
I am having a hard time mentally parsing your "something like" portion, but to give a generic example.
IF A THEN B ELSE C
can be translated to (A AND B) OR (NOT A AND C)
Note: Bill Braskey's "comment" is also worth considering. If the conditional logic gets complicated enough, it can be less work for the database to UNION queries with simpler conditions. You'd still need the condition in one to be A AND B and the other to be NOT A AND C to apply the conditions appropriately, but you'd be simplifying from the overall condition (especially when you consider "C" could actually be a translation of IF D THEN E ELSE F.
Maybe just take the easy way out and write two queries with the separate requirements and do a union

SQL GROUP BY function returning incorrect SUM amount

I've been working on this problem, researching what I could be doing wrong but I can't seem to find an answer or fault in the code that I've written. I'm currently extracting data from a MS SQL Server database, with a WHERE clause successfully filtering the results to what I want. I get roughly 4 rows per employee, and want to add together a value column. The moment I add the GROUP BY clause against the employee ID, and put a SUM against the value, I'm getting a number that is completely wrong. I suspect the SQL code is ignoring my WHERE clause.
Below is a small selection of data:
hr_empl_code hr_doll_paid
1 20.5
1 51.25
1 102.49
1 560
I expect that a GROUP BY and SUM clause would give me the value of 734.24. The value I'm given is 211461.12. Through troubleshooting, I added a COUNT(*) column to my query to work out how many lines it's running against, and it's giving a result of 1152, furthering reinforces my belief that it's ignoring my WHERE clause.
My SQL code is as below. Most of it has been generated by the front-end application that I'm running it from, so there is some additional code in there that I believe does assist the query.
SELECT DISTINCT
T000.hr_empl_code,
SUM(T175.hr_doll_paid)
FROM
hrtempnm T000,
qmvempms T001,
hrtmspay T166,
hrtpaytp T175,
hrtptype T177
WHERE 1 = 1
AND T000.hr_empl_code = T001.hr_empl_code
AND T001.hr_empl_code = T166.hr_empl_code
AND T001.hr_empl_code = T175.hr_empl_code
AND T001.hr_ploy_ment = T166.hr_ploy_ment
AND T001.hr_ploy_ment = T175.hr_ploy_ment
AND T175.hr_paym_code = T177.hr_paym_code
AND T166.hr_pyrl_code = 'f' AND T166.hr_paid_dati = 20180404
AND (T175.hr_paym_type = 'd' OR T175.hr_paym_type = 't')
GROUP BY T000.hr_empl_code
ORDER BY hr_empl_code
I'm really lost where it could be going wrong. I have stripped out the additional WHERE AND and brought it down to just T166.hr_empl_code = T175.hr_empl_code, but it doesn't make a different.
By no means am I any expert in SQL Server and queries, but I have decent grasp on the technology. Any help would be very appreciated!
Group by is not wrong, how you are using it is wrong.
SELECT
T000.hr_empl_code,
T.totpaid
FROM
hrtempnm T000
inner join (SELECT
hr_empl_code,
SUM(hr_doll_paid) as totPaid
FROM
hrtpaytp T175
where hr_paym_type = 'd' OR hr_paym_type = 't'
GROUP BY hr_empl_code
) T on t.hr_empl_code = T000.hr_empl_code
where exists
(select * from qmvempms T001,
hrtmspay T166,
hrtpaytp T175,
hrtptype T177
WHERE T000.hr_empl_code = T001.hr_empl_code
AND T001.hr_empl_code = T166.hr_empl_code
AND T001.hr_empl_code = T175.hr_empl_code
AND T001.hr_ploy_ment = T166.hr_ploy_ment
AND T001.hr_ploy_ment = T175.hr_ploy_ment
AND T175.hr_paym_code = T177.hr_paym_code
AND T166.hr_pyrl_code = 'f' AND T166.hr_paid_dati = 20180404
)
ORDER BY hr_empl_code
Note: It would be more clear if you have used joins instead of old style joining with where.

T-SQL Case Then Else Command inside Join

I have to preface this by telling you that I am just learning SQL. My task is to validate a report generated by T-SQL written by a consultant that used to work for our company. Can someone explain to me what the following section is doing? I understand the idea of a LEFT OUTER JOIN, but I don't understand how the case statement evaluates.
From
ShipmentQty
LEFT OUTER JOIN ShipmentCost ON
Case when ShipmentQty.RSLDNM <> 0 Then
0
Else
ShipmentQty.SDSHPN
End = ShipmentCost.FHSHPN
AND
ShipmentQty.RSLDNM = ShipmentCost.FHLDNM
I assume that the expression runs without error, but again, my task is not to run the SQL, only to validate each step of the code. Thank you in advance and please forgive my inexperience.
It just means that if ShipmentQty.RSLDNM is not 0, then use 0, otherwise, use ShipmentQty.SDSHPN
It can be easier to understand the logic without the case. This is probably the equivalent logic:
From ShipmentQty LEFT OUTER JOIN
ShipmentCost
ON ((ShipmentCost.FHSHPN = 0 AND ShipmentQty.RSLDNM <> 0) OR
(ShipmentCost.FHSHPN = ShipmentQty.SDSHPN AND ShipmentQty.RSLDNM = 0)
) AND
ShipmentQty.RSLDNM = ShipmentCost.FHLDNM
I say "probably" because this does not take NULL values of ShipmentQty.RSLDNM into account. So, if RSLDNM is zero, then the comparison is FHSHPN to SDSHPN. If RSLDNM is not zero, then FHSHPN needs to be zero.
the join is simple, the case is just a condition (Watch this link), when the field ShipmentQty.RSLDNM <> 0 then the join will use a 0 as value, if else the join will use ShipmentQty.SDSHPN as value.

Problem with adding custom sql to finder condition

I am trying to add the following custom sql to a finder condition and there is something not quite right.. I am not an sql expert but had this worked out with a friend who is..(yet they are not familiar with rubyonrails or activerecord or finder)
status_search = "select p.*
from policies p
where exists
(select 0 from status_changes sc
where sc.policy_id = p.id
and sc.status_id = '"+search[:status_id].to_s+"'
and sc.created_at between "+status_date_start.to_s+" and "+status_date_end.to_s+")
or exists
(select 0 from status_changes sc
where sc.created_at =
(select max(sc2.created_at)
from status_changes sc2
where sc2.policy_id = p.id
and sc2.created_at < "+status_date_start.to_s+")
and sc.status_id = '"+search[:status_id].to_s+"'
and sc.policy_id = p.id)" unless search[:status_id].blank?
My find statement:
Policy.find(:all,:include=>[{:client=>[:agent,:source_id,:source_code]},{:status_changes=>:status}],
:conditions=>[status_search])
and I am getting this error message in my log:
ActiveRecord::StatementInvalid (Mysql::Error: Operand should contain 1 column(s): SELECT DISTINCT `policies`.id FROM `policies` LEFT OUTER JOIN `clients` ON `clients`.id = `policies`.client_id WHERE ((((policies.created_at BETWEEN '2009-01-01' AND '2009-03-10' OR policies.created_at = '2009-01-01' OR policies.created_at = '2009-03-10')))) AND (select p.*
from policies p
where exists
(select 0 from status_changes sc
where sc.policy_id = p.id
and sc.status_id = '2'
and sc.created_at between 2009-03-10 and 2009-03-10)
or exists
(select 0 from status_changes sc
where sc.created_at =
(select max(sc2.created_at)
from status_changes sc2
where sc2.policy_id = p.id
and sc2.created_at < 2009-03-10)
and sc.status_id = '2'
and sc.policy_id = p.id)) ORDER BY clients.created_at DESC LIMIT 0, 25):
what is the major malfunction here - why is it complaining about the columns?
The conditions modifier is expecting a condition (e.g. a boolean expression that could go in a where clause) and you are passing it an entire query (a select statement).
It looks as if you are trying to do too much in one go here, and should break it down into smaller steps. A few suggestions:
use the query with find_by_sql and don't mess with the conditions.
use the rails finders and filter the records in the rails code
Also, note that constructing a query this way isn't secure if the values like status_date_start can come from users. Look up "sql injection attacks" to see what the problem is, and read the rails documentation & examples for find_by_sql to see how to avoid them.
Ok, I've managed to retool this so it is more friendly to a conditions modifier and I think it is doing the sql query correctly.. however, it is returning policies that when I try to list the current status (the policy.status_change.last.status) it is set to the same status used in the query - which is not correct
here is my updated condition string..
status_search = "status_changes.created_at between ? and ? and status_changes.status_id = ?) or
(status_changes.created_at = (SELECT MAX(sc2.created_at) FROM status_changes sc2
WHERE sc2.policy_id = policies.id and sc2.created_at < ?) and status_changes.status_id = ?"
is there something obvious to this that is not returning all of the remaining associated status changes once it finds the one in the query?
here is the updated find..
Policy.find(:all,:include=>[{:client=>[:agent,:source_id,:source_code]},:status_changes],
:conditions=>[status_search,status_date_start,status_date_end,search[:status_id].to_s,status_date_start,search[:status_id].to_s])