SQL CASE returning two values - sql

I'm writing my first SQL CASE statement and I have done some research on them. Obviously the actual practice is going to be a little different than what I read because of context and things of that nature. I understand HOW they work. I am just having trouble forming mine correctly. Below is my draft of the SQL statement where I am trying to return two values (Either a code value from version A and it's title or a code value from version B and its title). I've been told that you can't return two values in one CASE statment, but I can't figure out how to rewrite this SQL statement to give me all the values that I need. Is there a way to use a CASE within a CASE (as in a CASE statement for each column)?
P.S. When pasting the code I removed the aliases just to make it more concise for the post
SELECT
CASE
WHEN codeVersion = A THEN ACode, Title
ELSE BCode, Title
END
FROM Code.CodeRef
WHERE ACode=#useCode OR BCode=#useCode

A case statement can only return one value. You can easily write what you want as:
SELECT (CASE WHEN codeVersion = 'A' THEN ACode
ELSE BCode
END) as Code, Title
FROM Code.CodeRef
WHERE #useCode in (ACode, BCode);

A case statement can only return a single column. In your scenario, that's all that is needed, as title is used in either outcome:
SELECT
CASE
WHEN codeVersion = "A" THEN ACode,
ELSE BCode
END as Code,
Title
FROM Code.CodeRef
WHERE ACode=#useCode OR BCode=#useCode
If you actually did need to apply the case logic to more than one column, then you'd need to repeat it.

Here is what I normally use:
SELECT
CASE
WHEN codeVersion = "A" THEN 'ACode'
WHEN codeVersion = "B" THEN 'BCode'
ELSE 'Invalid Version'
END as 'Version',
Title
FROM Code.CodeRef
WHERE
CASE
WHEN codeVersion = "A" THEN ACode
WHEN codeVersion = "B" THEN BCode
ELSE 'Invalid Version'
END = 'Acode'
my suggestion uses an alias. note on aliases: unfortunately you can't use the alias 'Version' in a where/group by clause. You have to use the whole case statement again. I believe you can only use an alias in an Order By.

Related

Can I use different selection comparisons based on a passed value in SQL?

I wasn't really sure of the best wording for the question but here is my dilemma:
I am passing a value to a sql query as #district. This value may be the exact district but it also has the possibility of being a value that should create a set of multiple districts. So if I pass 002 I want the WHERE clause to say I.Offense_Tract = #district. If I pass Other I want the WHERE clause to say I.Offense_Tract in (). What I am trying to do is something like:
AND
CASE
WHEN #district = "Other" THEN I.Offense_Tract in ('BAR','COL','GER','MEM','MIL','JAIL','JAILEAST','SCCC','1USD','2USD')
ELSE I.Offense_Tract = #district
END
But this doesn't work. The problem, restated, is if the value passed is anything other than Other, I just want it to be =. If Other is passed, I want it to be IN.
You don't need the CASE expression.
You can apply this logic with operators AND and OR:
AND (
(#district = 'Other' AND I.Offense_Tract IN ('BAR','COL','GER','MEM','MIL','JAIL','JAILEAST','SCCC','1USD','2USD'))
OR
(#district <> 'Other' AND I.Offense_Tract = #district)
)
Note that, in databases like MySql, Postgresql and SQLite, your code would work as it is.

Check column IS NULL not working in Case Expression

I am trying to check a column which belongs to View "IS NULL" and it works good with select statement:
SELECT TOP (1000) [Invoice_Number]
,[Invoice_Date]
,[Invoice_Amount]
,[Invoice_CoCd]
,[Invoice_vendor]
,[Invoice_PBK]
,[Invoice_DType]
,[Invoice_DueDate]
,[Invoice_ClgDate] FROM [dbo].[viewABC] where Invoice_PBK IS NULL
Now I have an update statement, where I need to update a column in a table based on NULL in VIEW:
UPDATE cis
SET
cis.InvoiceStatus =
(
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD'
THEN '233' END)
FROM
[dbo.[tblABC] cis,
[dbo].[viewABC] imd
WHERE [condition logic]
These is no issue with where condition, the IS NULL in the CASE expression causing the problem.
Can someone help please?
You may want to just test your Logic piece by piece.
Try
SELECT ISNULL(RTRIM(LTRIM(imd.[Invoice_PBK])),'Hey Im Null')
FROM
[dbo].[tblABC] cis,
[dbo].[viewABC] imd
WHERE [condition logic]
See if you get that String value on your returned column(s) from the Query. Then, build from there. It could be something as simple as the JOIN. Which I'm not a fan of that old syntax but, without more info on this table other than [conditions]. It's hard to just guess an answer for you. You have no detailed evidence that helps us. It very well could be your conditions but, you're saying "condition logic" and that does nothing for the group on this thread.
Looking at this expression:
cis.InvoiceStatus =
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
END
And this symptom:
CIS.InvoiceStatus gets updated with NULL
The obvious conclusion is neither WHEN condition is met, and therefore the result of the CASE expression is NULL.
Maybe you wanted this, which will preserve the original value in that situation:
cis.InvoiceStatus =
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
ELSE
cis.InvoiceStatus
END
Or maybe you wanted this, to also match an empty string value:
cis.InvoiceStatus =
CASE
WHEN NULLIF(RTRIM(LTRIM(imd.[Invoice_PBK])),'') IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
END
It's also worth pointing out the two WHEN conditions are looking at two different columns.
Finally, it may be worth a data clean-up project here. Needing to do an LTRIM() will break any chance of using indexes on those fields (RTRIM() is slightly less bad), and index use cuts to the core of database performance.

Force result for field as 'NULL' when document was posted after a certain date

I have a query that I am pulling in a department field, however, after a certain date I want this field to be populated as null.
For example, here is the code
Select T6.Segment2 as 'Old Department Code'
I do want this field to pull in the appropriate values, however after a certain date ( 04/01/2019 ) I want this field to show a NULL value.
Is this possible?
Not sure which DBMS you are using but it is basically the same for all of them when it comes to this... You want to use a CASE statement.
What this essentially does is it acts as an IF ELSE in your SELECT.
So in your case (ha, pun) (T-SQL Syntax):
SELECT
CASE
WHEN (YourDateFieldHere) < '04/01/2019' THEN (YourOutputFieldHere)
ELSE NULL
END (AS Alias)
FROM ...
CASE statements can check for multiple criteria, it doesn't have to just be one or the other, in this case just include more lines of WHEN (something) THEN (display this)
You can use case..when
( considering YYYYMMDD is the default format used in SAP at the internal level )
Select case when myDate >'20190104' then
null
else
T6.Segment2
end
as 'Old Department Code'
From yourTable

Assign a case value to a column rather than an alias

This should be a simple one, but I have not found any solution:
The normal way is using an alias like this:
CASE WHEN ac_code='T' THEN 'time' ELSE 'purchase' END as alias
When using alias in conjunction with UNION ALL this causes problem because the alias is not treated the same way as the other columns.
Using an alias to assign the value is not working. It is still treated as alias, though it has the column name.
CASE WHEN ac_code='T' THEN 'time' ELSE 'purchase' END as ac_subject
I want to assign a value to a column based on a condition.
CASE WHEN ac_code='T' THEN ac_subject ='time' ELSE ac_subject='purchase' END
Now I get the error message
UNION types character varying and boolean cannot be matched
How can I assign a value to a column in a case statement without using an alias in the column (shared by other columns in UNION)?
Here is the whole (simplified) query:
SELECT hr_id,
CASE WHEN hr_subject='' THEN code_name ELSE hr_subject END
FROM hr
LEFT JOIN code ON code_id=hr_code
WHERE hr_job='123'
UNION ALL
SELECT po_id,
CASE WHEN po_subject='' THEN code_name ELSE po_subject END
FROM po
LEFT JOIN code ON code_id=po_code
WHERE po_job='123'
UNION ALL
SELECT ac_id,
CASE WHEN ac_code='T' THEN ac_subject='time' ELSE ac_subject='purchase' END
FROM ac
WHERE ac_job='123'
There is no alias in your presented query. You are confusing terms. This would be a column alias:
CASE WHEN hr_subject='' THEN code_name ELSE hr_subject END AS ac_subject
In a UNION query, the number of columns, column names and data types in the returned set are determined by the first row. All appended rows have to match the row type. Column names in appended rows (including aliases) are just noise and ignored. Maybe useful for documentation, nothing else.
The = operator does not assign anything in a SELECT query. It's the equality operator that returns a boolean value. TRUE if both operands are equal, etc. This returns a boolean value: ac_subject='time' Hence your error message:
UNION types character varying and boolean cannot be matched
The only way to "assign" a value to a particular output column in this query is to include it at the right position in the SELECT list.
The information in the question is incomplete, but I suspect you are also confusing the empty string ('') with the NULL value. A distinction that you need to understand before doing anything else with relational databases. Maybe start here. In this case you would rather use COALESCE to provide a default for NULL values:
SELECT hr_id, COALESCE(hr_subject, code_name) AS ac_subject
FROM hr
LEFT JOIN code ON code_id=hr_code
WHERE hr_job = '123'
UNION ALL
SELECT po_id, COALESCE(po_subject, code_name)
FROM po
LEFT JOIN code ON code_id=po_code
WHERE po_job = '123'
UNION ALL
SELECT ac_id, CASE WHEN ac_code = 'T' THEN 'time'::varchar ELSE 'purchase' END
FROM ac
WHERE ac_job = '123'
Just an educated guess, assuming type varchar. You should have added table qualification to column names to clarify their origin. Or table definitions to clarify everything.
The CASE expression is supposed to return a value, e.g. 'time'.
Your value is another expression subject ='time' which is a boolean (true or false).
Is this on purpose? Does the other query you glue with UNION have a boolean in that place, too? Probably not, and this is what the DBMS complains about.
I found the problem.
CASE WHEN hr_subject=’’ THEN code_name ELSE hr_subject END
The columns code_name and hr_subject was different length. This caused the unpredictable result. I think that aliases can work now.
Thank you for your support.

Trying to combine three individual SELECT statements into one main SELECT statement

Here's the problem. There are 3 fields in my table which may contain data with an extra quotation appended at the end. So, I'm trying to run a select statement that will remove this extra character from these fields, IF that extra character exists. I can write 3 individual queries just fine, and they work, but I'm trying to combine them all into one query. Here's what I have so far, and I know it's probably incorrect the way I have it:
Here's the result set that comes back. Notice that all three columns are NULL. They shouldn't be:
Here's an individual query that works for one field at a time:
Can you tell me what I'm doing wrong?
You can remove the WHEREs, as well as the non-correlated subqueries in the select list, and probably simplify it to this...
SELECT
AID
, EID
, STOREID
, [Language]
, 'BrandLabel' = CASE WHEN BrandLabel LIKE '%"'
THEN LEFT(BrandLabel, LEN(BrandLabel) -1)
ELSE BrandLabel
END
, 'Terms' = CASE WHEN Terms LIKE '%"'
THEN LEFT(Terms, LEN(Terms) -1)
ELSE Terms
END
, 'TrackOrderLbl' = CASE WHEN TrackOrderLbl LIKE '%"'
THEN LEFT(TrackOrderLbl, LEN(TrackOrderLbl) -1)
ELSE TrackOrderLbl
END
FROM parallel_Purchase_Email_Content_OMS WITH (NOLOCK)