SQL CONCAT statement with multiple conditions - sql

I have a table with output as of following:
I am trying to concat the outputs into a single output, given the conditions that:
When column fields (Type 1 to Type 5) IS NOT NULL OR '', take the value and combine it with another field with the same condition met
Expected output(based on screenshot above): RAM/TOTAL/N.A.
When column field (Type 6) IS NOT NULL OR '', display the result as OUT OF SERVICE, ignoring other values
Expected output: OUT OF SERVICE
Sample query:
SELECT CONCAT(Type1, '/' , Type2, '/' , Type3, '/' , Type4, '/' , Type5, '/' , Type6) AS OUTPUT FROM #myTable

You example screen shots do not agree with your expected output.
You say if Type6 is Null or blank, then it should say 'OUT OF SERVICE'
However, in your screen shot, your expected output concats the previous columns though Type6 is blank! Should it not say OUT OF SERVICE ??
Assuming that this is simply a typo.. what you could do is the following:
Set the values of the column to null if blank and then concat them in the subsequent select. Just one one many ways to do it..
;with mycte as
(select
'' as Type1
, 'RAM' as Type2
,'' as Type3
,'TOTAL' as Type4
,'N/A' as Type5
,'' as Type6
)
,set_null as (
select
Type1 = case when isnull(Type1,'') = '' then NULL else Type1+'/' end
,Type2 = case when isnull(Type2,'') = '' then NULL else Type2+'/' end
,Type3 = case when isnull(Type3,'') = '' then NULL else Type3 +'/'end
,Type4 = case when isnull(Type4,'') = '' then NULL else Type4+'/' end
,Type5 = case when isnull(Type5,'') = '' then NULL else Type5+'/' end
,Type6 = case when isnull(Type6,'') = '' then NULL else Type6 end
from mycte
)
select
case
when isnull(Type6,'') = '' then 'OUT OF SERVICE'
else concat(Type1+Type2,Type3,Type4,Type5,Type6)
end as concat_column
from set_null

You may try this. This is an approach use to remove unnecessary character added due to no null blank value from a string.
First create your string and remove the duplicate unnecessary / from the string.
At the end only need to check whether / is added in suffix or prefix which need to be removed, by using simple case and substring you can achieve the same.
;with cte as
(select 'sd' as Type1, 'RAM' as Type2,'' as Type3,'TOTAL' as Type4,'N.A' as Type5,null as Type6)
,ct as (
SELECT case when Type6 is null ---- you may chnage your condition of checking Type6 is over there
then 'OUT OF SERVICE'
else REPLACE( REPLACE( CONCAT('][', Type1, '][' , Type2, '][' , Type3, '][' , Type4, '][' , Type5, '][' , Type6), '[]', ''), '][', '/')
End AS OUTP FROM cte
)
select
case when OUTP like '/%'
then case when OUTP like '%/'
then SUBSTRING( OUTP, 2, len(OUTP)-2 )
else SUBSTRING( OUTP, 2, len(OUTP)-1 ) end
else case when OUTP like '%/'
then SUBSTRING( OUTP, 1, len(OUTP)-1 )
else OUTP end
End as OUTPU
from ct

Related

CASE statement for rows not existing on joined table

I am trying to wrap the inner CASE statements below with an outer CASE statement to output '00-00-00-00-00' if there is not a matching row found on the left-joined OtherTable C , instead what is happening is when there is not a row found in OtherTable C then it is outputting ---- (just dashes).
SELECT A.INV_ITEM_ID,
CASE WHEN C.INV_ITEM_ID '' THEN '00-00-00-00-00'
ELSE ( CONCAT(CASE WHEN C.STORAGE_AREA like '[0-9]'
THEN '0'+ C.STORAGE_AREA
WHEN C.STORAGE_AREA = '' THEN '00'
ELSE C.STORAGE_AREA END ,'-', CASE WHEN C.STOR_LEVEL_1 like '[0-9]'
THEN '0' + C.STOR_LEVEL_1
WHEN C.STOR_LEVEL_1 = '' THEN '00'
ELSE C.STOR_LEVEL_1 END , '-',
CASE WHEN C.STOR_LEVEL_2 like '[0-9]'
THEN '0' + C.STOR_LEVEL_2
WHEN C.STOR_LEVEL_2 = '' THEN '00'
ELSE C.STOR_LEVEL_2 END, '-',
CASE WHEN C.STOR_LEVEL_3 like '[0-9]'
THEN '0' + C.STOR_LEVEL_3
WHEN C.STOR_LEVEL_3 = '' THEN '00'
ELSE C.STOR_LEVEL_3 END, '-',
CASE WHEN C.STOR_LEVEL_4 like '[0-9]'
THEN '0' + C.STOR_LEVEL_4
WHEN C.STOR_LEVEL_4 = '' THEN '00'
ELSE C.STOR_LEVEL_4 END ) ) END
FROM MyTable A
LEFT OUTER JOIN OtherTable C ON C.INV_ITEM_ID = A.INV_ITEM_ID
Is there a way to achieve this without having to use a Sub-query here?
If there is no match in a left join the OtherTable value will be null not ''
So when you say this:
CASE WHEN C.INV_ITEM_ID '' THEN '00-00-00-00-00'
You are checking if there is a zero length string or '' in the field c.INV_ITEM_ID
Instead you should use
CASE WHEN C.INV_ITEM_ID is null THEN '00-00-00-00-00'
You likely do not have any c.INV_ITEM_ID with string value ''. So when there is no matching data in the left join (ie the value is null) the case expression moves on and performs a concatenation. Each sub-case expression checks for c.STOR_LEVEL_1 and doesn't have a match so goes with the "else" or C.STOR_LEVEL_1. So what you actually have is
concat(null,'-',null,'-',null,'-',null,'-')
Which evaluates to ----
Might be able to cut your SQL down a bit:
SELECT
A.INV_ITEM_ID,
CONCAT(
RIGHT(CONCAT('00', C.STOR_LEVEL_1), 2), '-',
RIGHT(CONCAT('00', C.STOR_LEVEL_2), 2), '-',
RIGHT(CONCAT('00', C.STOR_LEVEL_3), 2), '-',
RIGHT(CONCAT('00', C.STOR_LEVEL_4), 2)
) as x
CONCAT behaves slightly differently to + with NULL. CONCAT treats null as emptystring, but + will nullify the whole expression. This, whether your column is null, a single digit or double digit, if you CONCAT it onto '00' then take the rightmost 2 you end up with a 2 digits number (00 if null, 0x if one digit, xx if 2).

How to check if field is NULL and blank?

I'm trying to remove the possibility of blank spaces by a value not existing in the database when creating the view for my lookup. The issue I'm having is that my CASE statement isn't working quite right when I'm trying to check for a NULL or blank value. It seems to work for those that are null but the blank doesn't seem to have as much luck. In this case I am trying to check for null or blank of importantField
CREATE VIEW Lookup4 AS
SELECT TOP 140000 CONCAT(no,
CASE WHEN (importantField is null OR importantField = '')
THEN '' ELSE ' ' + importantField END,
fieldname + ' ', anotherField2) AS UNRELATEDFIELD, Code,
CASE NAME
WHEN '101,,,,,' THEN 'value1e'
WHEN '14,,,,,' THEN 'value3'
WHEN '16,,,,,' THEN 'value4'
END AS NAME
FROM dbo.Lookup
Is this what you are after
CREATE VIEW Lookup4 AS
SELECT TOP 140000 CONCAT(no,
CASE WHEN (ISNULL(importantField,'') = '')
THEN '' ELSE ' ' + importantField END,
fieldname + ' ', anotherField2) AS UNRELATEDFIELD, Code,
CASE NAME
WHEN '101,,,,,' THEN 'value1e'
WHEN '14,,,,,' THEN 'value3'
WHEN '16,,,,,' THEN 'value4'
END AS NAME
FROM dbo.Lookup
If you only want to check for null and not for empty strings then you can also use ifnull as you tried. But that is not suitable for empty strings too.
SELECT IF(field1 IS NULL or field1 = '', 'empty', field1) as field1
from tablename
Try to change:
importantField is null
with
IsNull(importantField)
CREATE VIEW Lookup4 AS
SELECT TOP 140000 CONCAT(no,ifnull(importantField,'')<>'',
fieldname + ' ', anotherField2) AS UNRELATEDFIELD, Code,
CASE NAME
WHEN '101,,,,,' THEN 'value1e'
WHEN '14,,,,,' THEN 'value3'
WHEN '16,,,,,' THEN 'value4'
END AS NAME
FROM dbo.Lookup
Minor changes according to your result
Method 1:
Select *
From dbo.Lookup
Where IsNull(importantField, '') = ''
Method 2:
Select *
From dbo.Lookup
Where (importantField is NULL or importantField = '')

CONCAT with IF condition in SQL Server

I have a table with four columns presenting {YES, NO, N/A} values. What I'd like to obtain is a column with concatenated names of those columns which present a 'YES' value separate by a double underscore.
\, A, B, C, D
1, YES, NO, YES, N/A
2, NO, YES, N/A, N/A
3, YES, NO, NO, YES
Expected result:
A__C
B
A__D
Something like:
select CONCAT(
IF(A = 'YES', 'A'),
IF(B = 'YES', 'B'),
IF(C = 'YES', 'C'),
IF(D = 'YES', 'D'))
from my_table
Hope I understand you right, that you want a double underscore separator.
This solution works without any subquery or cte processing.
select substring(
iif(a='YES','__A','') + iif(b='YES','__B','') +
iif(c='YES','__C','') + iif(d='YES','__D','')
,3,100)
from table1
One should know that this: substring('', 3, 100) will work using SqlServer.
Assuming T1 is your table:
SELECT CASE WHEN LEN(X)>0 THEN LEFT(X, LEN(X)-2) ELSE '' END AS Y
FROM (
SELECT
CASE WHEN A='YES' THEN 'A__' ELSE '' END + CASE WHEN B='YES' THEN 'B__' ELSE '' END + CASE WHEN C='YES' THEN 'C__' ELSE '' END + CASE WHEN D='YES' THEN 'D__' ELSE '' END AS X
FROM T1
) A
WITH ABC
as
(
Select
(
CASE WHEN A = 'YES' THEN 'A_' ELSE '' END as A +
CASE WHEN B = 'YES' THEN 'B_' ELSE '' END as B +
CASE WHEN C = 'YES' THEN 'C_' ELSE '' END as C +
CASE WHEN D = 'YES' THEN 'D_' ELSE '' END as D
) as output
)
Select case when len(output) = 2 then left (output,1)
else output
end as output
From ABC
Select case A then 'YES' then 'A' else '_'end + case B then 'YES' then 'B' else '_'end +case C then 'YES' then 'C' else '_'end +case D then 'YES' then 'D' else '_'end as result from my_table

Show column names having null values in row

I would like to display only those column name against the student id whose question(q1,q2,q3,q4...etc) value is null below is the printscreen of table against the id i would like to have question id . with below expected o/p
You can use FOR XML to achieve the result:
SQL Fiddle
;WITH Cte AS(
SELECT id, name, q = 'q1' FROM Test WHERE q1 IS NULL UNION ALL
SELECT id, name, q = 'q2' FROM Test WHERE q2 IS NULL UNION ALL
SELECT id, name, q = 'q3' FROM Test WHERE q3 IS NULL UNION ALL
SELECT id, name, q = 'q4' FROM Test WHERE q4 IS NULL UNION ALL
SELECT id, name, q = 'q5' FROM Test WHERE q5 IS NULL UNION ALL
SELECT id, name, q = 'q6' FROM Test WHERE q6 IS NULL
)
SELECT
id,
name,
incompletes = STUFF((
SELECT ',' + c2.q
FROM Cte c2
WHERE
c1.id = c2.id
AND c1.name = c2.name
GROUP BY c2.id, c2.name, c2.q
FOR XML PATH(''), TYPE).value('.', 'varchar(max)')
, 1, 1, '')
FROM Cte c1
GROUP BY c1.id, c1.name
ORDER BY c1.id, c1.name
SELECT ID, NAME,
RTRIM ((CASE WHEN Q1 IS NULL THEN 'Q1,' END)||
(CASE WHEN Q2 IS NULL THEN 'Q2,' END)||
(CASE WHEN Q3 IS NULL THEN 'Q3,' END)||
(CASE WHEN Q4 IS NULL THEN 'Q4,' END)||
(CASE WHEN Q5 IS NULL THEN 'Q5,' END)||
(CASE WHEN Q6 IS NULL THEN 'Q6,' END),',') AS NULL_QUESTIONS
FROM TABLE
EDIT: Added STUFF to get rid of the leading comma and added ELSE '':
SELECT ID, NAME,
STUFF (
CASE WHEN Q1 IS NULL THEN ',q1' ELSE '' END +
CASE WHEN Q2 IS NULL THEN ',q2' ELSE '' END +
CASE WHEN Q3 IS NULL THEN ',q3' ELSE '' END +
CASE WHEN Q4 IS NULL THEN ',q4' ELSE '' END +
CASE WHEN Q5 IS NULL THEN ',q5' ELSE '' END +
CASE WHEN Q6 IS NULL THEN ',q6' ELSE '' END
, 1,1,'') AS NULL_QUESTIONS
FROM Test
SELECT Panelist_ID, EmailAddress collate Latin1_General_CI_AI,
STUFF (
CASE WHEN convert (nvarchar (14), PQ_160175) IS NULL THEN ',PQ_160175' ELSE '' END +
CASE WHEN convert (nvarchar (14), PQ_161979) IS NULL THEN ',PQ_161979' ELSE '' END +
CASE WHEN convert (nvarchar (14), PQ_161980) IS NULL THEN ',PQ_161980' ELSE '' END +
CASE WHEN convert (nvarchar (14), PQ_161981) IS NULL THEN ',PQ_161981' ELSE '' END +
CASE WHEN convert (nvarchar (14), PQ_161982) IS NULL THEN ',PQ_161982' ELSE '' END +
CASE WHEN convert (nvarchar (14), PQ_161983) IS NULL THEN ',PQ_161983' ELSE '' END +
CASE WHEN convert (nvarchar (14), PQ_161986) IS NULL THEN ',PQ_161986' ELSE '' END +
CASE WHEN PQ_172469 IS NULL THEN ',PQ_172469' ELSE '' END +
CASE WHEN PQ_180972 IS NULL THEN ',PQ_180972' ELSE '' END +
CASE WHEN PQ_180973 IS NULL THEN ',PQ_180973' ELSE '' END +
CASE WHEN PQ_189924 IS NULL THEN ',PQ_189924' ELSE '' END +
CASE WHEN PQ_195859 IS NULL THEN ',PQ_195859' ELSE '' END +
CASE WHEN PQ_195860 IS NULL THEN ',PQ_195860' ELSE '' END +
CASE WHEN PQ_196605 IS NULL THEN ',PQ_196605' ELSE '' END +
CASE WHEN PQ_196606 IS NULL THEN ',PQ_196606' ELSE '' )
i have been using the aboce case statement and i am not able to see the output after 161983 nos

how can i use LRTIM and RTRIM to find invalid records and insert it into error table?

I have a query that finds the invalid records from each column in a table. but the length of the data type is not same for all the columns. I am saying this because when I use LTRIM and RTRIM , it gives an error "The type of column "SubscriberLastName" conflicts with the type of other columns specified in the UNPIVOT list" and if I CAST that column then no result.
Can anybody help me with that?
Insert into ErrorTable (------) select (-----)
From (
select [SubscriberDataId]
,Case When ltrim(rtrim([SubscriberCode])) = '' Then [SubscriberCode] Else 'CorrectValue' end as [SubscriberCode]
,Case When ltrim(rtrim([SubscriberLastName]))= '' Then [SubscriberLastName] Else 'CorrectValue' end as [SubscriberLastName]
,Case When ltrim(rtrim([SubscriberFirstName]))= '' Then [SubscriberFirstName] Else 'CorrectValue' end as [SubscriberFirstName]
from Facets.SubscriberData) [sd]
Unpivot
(ErrorValue for FieldName in ([SubscriberCode],
[SubscriberLastName],[SubscriberFirstName] )) as x
where x.ErrorValue <> 'CorrectValue'
You need to make sure the TYPEs are the same, not just the lengths.
Insert into ErrorTable (------) select (-----)
From (
select [SubscriberDataId]
,Case When ltrim(rtrim([SubscriberCode])) = '' Then CAST([SubscriberCode] AS NVARCHAR(MAX)) Else 'CorrectValue' end as [SubscriberCode]
,Case When ltrim(rtrim([SubscriberLastName]))= '' Then CAST([SubscriberLastName] AS NVARCHAR(MAX)) Else 'CorrectValue' end as [SubscriberLastName]
,Case When ltrim(rtrim([SubscriberFirstName]))= '' Then CAST([SubscriberFirstName] AS NVARCHAR(MAX)) Else 'CorrectValue' end as [SubscriberFirstName]
from Facets.SubscriberData) [sd]
Unpivot
(ErrorValue for FieldName in ([SubscriberCode],
[SubscriberLastName],[SubscriberFirstName] )) as x
where x.ErrorValue <> 'CorrectValue'