Case statement with 'not like' possible? - tsql

I’m looking to case all bacheloreatte degrees that are not BA’s or BS’s seperately (BSAST for example). I tried a nested case statement, but as I’m relatively new to t-sql I'm not sure if it was my syntax or that it’s not possible. Note that this is in a select statement.
SELECT
t2.ID,
t2.ACAD_PROGRAM,
'092013' AS T01,
'274842' AS T02,
REPLACE(p.SSN,'-','') AS T03,
'5' AS T04,
ap.ACPG_CIP AS T05,
CASE(t2.ACAD_PROGRAM)
WHEN 'BA%' THEN '1'
WHEN 'BS' THEN '2'
ELSE (CASE
WHEN t4.STP_DEGREE LIKE 'BA%'
THEN '1' END)
END AS T06

CASE has two formats, to be able to use with LIKE operator, your first CASE should be a Searched Case:
SELECT t2.ID, t2.ACAD_PROGRAM, '092013' AS T01, '274842' AS T02,
REPLACE(p.SSN,'-','') AS T03, '5' AS T04, ap.ACPG_CIP AS T05,
CASE WHEN t2.ACAD_PROGRAM LIKE 'BA%' THEN '1'
WHEN t2.ACAD_PROGRAM = 'BS' THEN '2'
ELSE
CASE WHEN t4.STP_DEGREE LIKE 'BA%' THEN '1' END
END AS T06
FROM yourTable

Related

TSQL if statement within

I have 160 columns like below
name,preweight,postweight,prebp,postbp,presugar,postsugar...
I am trying to include new column at the end for the list of factors (like weight is different between pre and post, sugar is different pre and post.).
Written sql like below
select name,preweight,postweight,prebp,postbp,presugar,postsugar
case
when (preweight!=postweight)
then 'weight changed'
when (presugar!=postsugar)
then 'sugar changed'
end
from clientinfo
now always shows one changed. but how I can list all the factors which are changed?
One option uses concat_ws() and a series of case expressions:
select
name,
preweight,
postweight,
prebp,
postbp,
presugar,
postsugar
concat_ws(
', '
case when preweight <> postweight then 'weight changed' end,
case when prebp <> postbp then 'bp changed' end,
case when presugar <> postsugar then 'sugar changed' end
) what_changed
from clientinfo

How do i use the like operator in a case select for Postgres SQL?

I would like to write an SQL statement with a CASE WHEN clause that uses the LIKE operator but I am not sure how to properly format the statement.
SELECT
services.id,
(CASE services.description
WHEN LIKE '%-'
THEN services.amount * -1
ELSE services.amount
END) AS service_amount
FROM services
Try it on this way:
SELECT
services.id,
CASE WHEN services.description LIKE '%-'
THEN services.amount * -1
ELSE services.amount
END) AS service_amount
FROM services

Case when SQL statement into variable

I need to create a variable for a case when statement on sybase sql. I have this error from my sql client
A SELECT statement that assigns a value to a variable must not be
combined with data-retrieval operations.
What do I need to do to use this variable the right way?
DECLARE #OutputName CHAR(50)
SELECT #OutputName=
(case when (a.M_TRN_TYPE='XSW' or a.M_TRN_TYPE='SWLEG') then 'FXSW'
when (a.M_TRN_TYPE<>'SWLEG' and a.M_TP_DVCS='C') then 'DCS'
when a.M_TRN_TYPE<>'SWLEG' and a.M_TP_DVCS<>'C' and SUBSTRING(c.M_SP_SCHED0,1,2)='+1' then
(case when b.M_DTE_SKIP_1>=a.M_TP_DTEEXP then 'SPOT' else 'OUTR' end)
when a.M_TRN_TYPE<>'SWLEG' and a.M_TP_DVCS<>'C' and SUBSTRING(c.M_SP_SCHED0,1,2)<>'+1' then
(case when b.M_DTE_SKIP_2>=a.M_TP_DTEEXP then 'SPOT' else 'OUTR' end)
end),
case when #OutputName='XSW' and
(case when c.M_DATESKIP='+1OD' then b.M_DTE_SKIP_1 else b.M_DTE_SKIP_2 end)=a.M_TP_DTEFST
then 0
else a.M_NB
end as 'NBI'
from TP_COMPL_PL_REP b
join TP_ALL_REP a on (a.M_NB=b.M_NB and a.M_REF_DATA=b.M_REF_DATA)
left join DM_SPOT_CONTRACT_REP c on (a.M_NB=c.M_NB and a.M_REF_DATA=c.M_REF_DATA)
The problem is that you can't combine a SELECT which sets a variable with a SELECT which returns data on the screen.
You set #OutputName to (case when (a.M_TRN_TYPE='XSW' .. ) but in the same SELECT you're also trying to display the results of:
case
when #OutputName='XSW' and
(case
when c.M_DATESKIP='+1OD'
then b.M_DTE_SKIP_1
else b.M_DTE_SKIP_2
end)=a.M_TP_DTEFST
then 0
else a.M_NB
end as 'NBI'
You can't have these two in the same SELECT, in the format you're using. My recommendation is to split them, one for assigning the variable:
DECLARE #OutputName CHAR(50)
SELECT #OutputName=
(case when (a.M_TRN_TYPE='XSW' or a.M_TRN_TYPE='SWLEG') then 'FXSW'
when (a.M_TRN_TYPE<>'SWLEG' and a.M_TP_DVCS='C') then 'DCS'
when a.M_TRN_TYPE<>'SWLEG' and a.M_TP_DVCS<>'C' and SUBSTRING(c.M_SP_SCHED0,1,2)='+1' then
(case when b.M_DTE_SKIP_1>=a.M_TP_DTEEXP then 'SPOT' else 'OUTR' end)
when a.M_TRN_TYPE<>'SWLEG' and a.M_TP_DVCS<>'C' and SUBSTRING(c.M_SP_SCHED0,1,2)<>'+1' then
(case when b.M_DTE_SKIP_2>=a.M_TP_DTEEXP then 'SPOT' else 'OUTR' end)
end)
from TP_COMPL_PL_REP b
join TP_ALL_REP a on (a.M_NB=b.M_NB and a.M_REF_DATA=b.M_REF_DATA)
left join DM_SPOT_CONTRACT_REP c on (a.M_NB=c.M_NB and a.M_REF_DATA=c.M_REF_DATA)
and one for returning the data:
SELECT case when #OutputName='XSW' and
(case when c.M_DATESKIP='+1OD' then b.M_DTE_SKIP_1 else b.M_DTE_SKIP_2 end)=a.M_TP_DTEFST
then 0
else a.M_NB
end as 'NBI'
from TP_COMPL_PL_REP b
join TP_ALL_REP a on (a.M_NB=b.M_NB and a.M_REF_DATA=b.M_REF_DATA)
left join DM_SPOT_CONTRACT_REP c on (a.M_NB=c.M_NB and a.M_REF_DATA=c.M_REF_DATA)

How do I use T-SQL's Case/When?

I have a huge query which uses case/when often. Now I have this SQL here, which does not work.
(select case when xyz.something = 1
then
'SOMETEXT'
else
(select case when xyz.somethingelse = 1)
then
'SOMEOTHERTEXT'
end)
(select case when xyz.somethingelseagain = 2)
then
'SOMEOTHERTEXTGOESHERE'
end)
end) [ColumnName],
Whats causing trouble is xyz.somethingelseagain = 2, it says it could not bind that expression. xyz is some alias for a table which is joined further down in the query. Whats wrong here? Removing one of the 2 case/whens corrects that, but I need both of them, probably even more cases.
SELECT
CASE
WHEN xyz.something = 1 THEN 'SOMETEXT'
WHEN xyz.somethingelse = 1 THEN 'SOMEOTHERTEXT'
WHEN xyz.somethingelseagain = 2 THEN 'SOMEOTHERTEXTGOESHERE'
ELSE 'SOMETHING UNKNOWN'
END AS ColumnName;
As soon as a WHEN statement is true the break is implicit.
You will have to concider which WHEN Expression is the most likely to happen. If you put that WHEN at the end of a long list of WHEN statements, your sql is likely to be slower. So put it up front as the first.
More information here: break in case statement in T-SQL
declare #n int = 7,
#m int = 3;
select
case
when #n = 1 then
'SOMETEXT'
else
case
when #m = 1 then
'SOMEOTHERTEXT'
when #m = 2 then
'SOMEOTHERTEXTGOESHERE'
end
end as col1
-- n=1 => returns SOMETEXT regardless of #m
-- n=2 and m=1 => returns SOMEOTHERTEXT
-- n=2 and m=2 => returns SOMEOTHERTEXTGOESHERE
-- n=2 and m>2 => returns null (no else defined for inner case)
If logical test is against a single column then you could use something like
USE AdventureWorks2012;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
More information - https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017

SELECT..CASE - Refactor T-SQL

Can I refactor the below SQL CASE statements into single for each case ?
SELECT
CASE RDV.DOMAIN_CODE WHEN 'L' THEN CN.FAMILY_NAME ELSE NULL END AS [LEGAL_FAMILY_NAME],
CASE RDV.DOMAIN_CODE WHEN 'L' THEN CN.GIVEN_NAME ELSE NULL END AS [LEGAL_GIVEN_NAME],
CASE RDV.DOMAIN_CODE WHEN 'L' THEN CN.MIDDLE_NAMES ELSE NULL END AS [LEGAL_MIDDLE_NAMES],
CASE RDV.DOMAIN_CODE WHEN 'L' THEN CN.NAME_TITLE ELSE NULL END AS [LEGAL_NAME_TITLE],
CASE RDV.DOMAIN_CODE WHEN 'P' THEN CN.FAMILY_NAME ELSE NULL END AS [PREFERRED_FAMILY_NAME],
CASE RDV.DOMAIN_CODE WHEN 'P' THEN CN.GIVEN_NAME ELSE NULL END AS [PREFERRED_GIVEN_NAME],
CASE RDV.DOMAIN_CODE WHEN 'P' THEN CN.MIDDLE_NAMES ELSE NULL END AS [PREFERRED_MIDDLE_NAMES],
CASE RDV.DOMAIN_CODE WHEN 'P' THEN CN.NAME_TITLE ELSE NULL END AS [PREFERRED_NAME_TITLE]
FROM dbo.CLIENT_NAME CN
JOIN dbo.REFERENCE_DOMAIN_VALUE RDV
ON CN.NAME_TYPE_CODE = RDV.DOMAIN_CODE AND RDV.REFERENCE_DOMAIN_ID = '7966'
No, you will require 8 separate statements as case and other such variants can only be used in a select to modify the results of a single column, not a series of columns.
If RDV.DOMAIN_COD can only by 'P' or 'L' use NULLIf. It's cleaner.
NULLIF ( expression , expression )
NULLIF is equivalent to a searched CASE expression in which the two expressions are equal and the resulting expression is NULL.
SELECT
NullIf('P', RDV.DOMAIN_CODE) AS [LEGAL_FAMILY_NAME],
...
NullIf('L', RDV.DOMAIN_CODE) AS [PREFERRED_FAMILY_NAME],
...
Since a CASE expression returns a single value, you cannot take eight CASE expressions returning 8 values and make a single CASE expression that returns all eight.
A less efficient alternative with no cases:
SELECT LEGAL_FAMILY_NAME, LEGAL_GIVEN_NAME, LEGAL_MIDDLE_NAMES, LEGAL_NAME_TITLE,
PREFERRED_FAMILY_NAME, PREFERRED_GIVEN_NAME, PREFERRED_MIDDLE_NAMES, PREFERRED_NAME_TITLE
FROM dbo.REFERENCE_DOMAIN_VALUE RDV
LEFT OUTER JOIN
( SELECT
NAME_TYPE_CODE,
FAMILY_NAME AS [LEGAL_FAMILY_NAME],
GIVEN_NAME AS [LEGAL_GIVEN_NAME],
MIDDLE_NAMES AS [LEGAL_MIDDLE_NAMES],
NAME_TITLE AS [LEGAL_NAME_TITLE]
FROM dbo.CLIENT_NAME
WHERE NAME_TYPE_CODE = 'L') LN ON RDV.DOMAIN_CODE = LN.NAME_TYPE_CODE
LEFT OUTER JOIN
( SELECT
NAME_TYPE_CODE,
FAMILY_NAME AS [PREFERRED_FAMILY_NAME],
GIVEN_NAME AS [PREFERRED_GIVEN_NAME],
MIDDLE_NAMES AS [PREFERRED_MIDDLE_NAMES],
NAME_TITLE AS [PREFERRED_NAME_TITLE]
FROM dbo.CLIENT_NAME
WHERE NAME_TYPE_CODE = 'P') PN ON RDV.DOMAIN_CODE = PN.NAME_TYPE_CODE
WHERE RDV.REFERENCE_DOMAIN_ID = '7966'
You could also use a temp table or table variable with all 8 columns and then do two inserts. You could also use a UNION ALL. My guess is that the 8 case statements are the most efficient way. This is especially true if you have some key where you will want some type of ClientID, Legal Names, Preferred Names so you will wrap a MAX around the cases or something and group by a ClientID......
You could generate the SQL script using syscols/INFORMATION_SCHEMA.columns with two case whens for each column 'CASE WHEN DOMAIN_CODE = ''P'' THEN ' + COLUMN_NAME + ' ELSE NULL END AS PREFERRED_' + COLUMN_NAME and then another for L. You could make a LOOP so that the same code executes once for P and once for L and get it down to one loop. Then you could EXEC the string directly, or PRINT it and put it into your SQL script. Anyway for just 8 columns I would cut/paste the case statements...
But anyway in general T-SQL is limited on being able to do for eaches over columns. Either you generate the script using a code generator (done in t-sql or another programming language) or you rethink your problem in another way. But many times you get better performance from duplicate cut/paste code. And many times it isn't worth the hassle of writing an external code generator (ie just for 8 case statements).