SQL - want to write unique error value per IF condition - sql

I'm handing lots of data and error checking it to ensure that it follows a correct format. So I'm creating a lot of IF conditions and so far I can group lots of conditions but only output one kind of error .. or i end up writing a heck of a lot of code per condition, just to have a crystal clear error output.
Is there a way to put into the IF condition a specific error output string?
Here is my code:
-- set the initial #IntHosp_SUM value
SELECT #IntHosp_SUM = 0
-- Store the sum value to #IntHosp_SUM
SELECT #IntHosp_SUM =
(
(COALESCE (CASE WHEN #Int1_5hosp = 1 THEN COUNT (Int1_5) ELSE NULL END, 0)) +
(COALESCE (CASE WHEN #Int2_5hosp = 1 THEN COUNT (Int2_5) ELSE NULL END, 0)) +
(COALESCE (CASE WHEN #Int3_5hosp = 1 THEN COUNT (Int3_5) ELSE NULL END, 0)) +
(COALESCE (CASE WHEN #Int4_5hosp = 1 THEN COUNT (Int4_5) ELSE NULL END, 0)) +
(COALESCE (CASE WHEN #Int5_5hosp = 1 THEN COUNT (Int5_5) ELSE NULL END, 0)) +
(COALESCE (CASE WHEN #Int6_5hosp = 1 THEN COUNT (Int6_5) ELSE NULL END, 0))
)
FROM ASSSIST2_M0Teacher
-- Check RESUSE_SUM Value against Intervention Entries
SELECT #ErrorID = IsNull(Max(ErrorID) + 1, 1)
FROM ErrorTemp
WHERE (Quest = #DB + #Quest) AND (ValidateID = #ValidateID)
SELECT #Error = 0
IF (#IntHosp_SUM = 1 and #Hosp1_info is null )
or (#IntHosp_SUM = 2 and (#Hosp1_info is null or #Hosp2_info is null))
or (#IntHosp_SUM >=3 and (#Hosp1_info is null or #Hosp2_info is null or #Hosp3_info is null))
or (#IntHosp_SUM = 0 and (#Hosp1_info is not null or #Hosp2_info is not null or #Hosp3_info is not null ))
or (#IntHosp_SUM = 1 and (#Hosp2_info is not null or #Hosp3_info is not null ))
or (#IntHosp_SUM >= 2 and #Hosp3_info is not null)
BEGIN
SELECT #Error = 1
END
BEGIN
IF #Error = 1
INSERT INTO ErrorTemp
(Quest,
ValidateID,
ErrorID,
ErrorType,
ErrorDesc,
Field)
VALUES (#DB + #Quest,
#ValidateID,
#ErrorID,
'Validation',
'Too much or no info present, so incorrect',
'Hosp Info - admissions')
SELECT #ErrorID = #ErrorID + 1
END
I have declared all variables and where they are in the DB, but didn't want to clutter with extra code. You can see that I sum a series of fields if they contain the value 1 .. I don't want to add any other values, just those with '1'.
My IF conditions then check if that if there is a sum of 1, there is one entry. If 2, then two entries .. we have to be thorough and check the inverse of that, so if the sum value is 0, then no entries are made and so forth.
Is there a way to pass a string from the IF / OR condition to the error output so that I can write a unique error per condition?
SQL Server Management Studio 17.2

Related

How to convert the below SQL query to work in snowflake?

SELECT
LEFT(Replace([SERIAL_NBR],'"',''),34) AS [SERIAL_NBR]
,CONVERT(datetime, Replace([INSERTED_DTM],'"',''), 103) AS [INSERTED_DTM]
,LEFT(Replace([GROUP_NAME],'"',''),1024)
,LEFT(Replace([FIRST_NAME],'"',''),50)
,LEFT(Replace([LAST_NAME],'"',''),50)
,LEFT(Replace([REASON_CODE_ID],'"',''),30)
,CASE isnumeric(Replace([VALUE],'"',''))
when 1
then CAST(Replace([VALUE],'"','') AS float)
else null
END AS [VALUE]
,LEFT(Replace([AUTOLOAD_DELIVERY_STATE_ID],'"',''),15)
,LEFT(Replace([RIDER_CLASS],'"',''), 20)
,LEFT(Replace([ADJUSTMENT_NOTES],'"',''), 1024)
FROM X
This is what I changed it to
SELECT
LEFT(Replace(SERIAL_NBR,'"',''),34) AS SERIAL_NBR
,to_timestamp(Replace(INSERTED_DTM,'"',''), 'DD/MM/YYYY') AS INSERTED_DTM
,LEFT(Replace(GROUP_NAME,'"',''),1024)
,LEFT(Replace(FIRST_NAME,'"',''),50)
,LEFT(Replace(LAST_NAME,'"',''),50)
,LEFT(Replace(REASON_CODE_ID,'"',''),30)
,CASE
WHEN is_Double(Replace(VALUE,'"','')) = 1
THEN CAST(Replace(VALUE,'"','') AS NUMBER)
ELSE NULL
END AS VALUE
,LEFT(Replace(AUTOLOAD_DELIVERY_STATE_ID,'"',''),15)
,LEFT(Replace(RIDER_CLASS,'"',''), 20)
,LEFT(Replace(ADJUSTMENT_NOTES,'"',''), 1024)
FROM stage."TL_A2_Adjustment_Note"
WHERE Replace(SERIAL_NBR,'"','') != 'A2'
It's giving me the error
001044 (42P13): SQL compilation error: error line 9 at position 9
At WHEN is_Double(Replace(VALUE,'"','')) = 1
The case statement is saying "when it can be parsed as a double/numeric do so, else use NULL"
Thus is snowflake this section:
,CASE
WHEN is_Double(Replace(VALUE,'"','')) = 1
THEN CAST(Replace(VALUE,'"','') AS NUMBER)
ELSE NULL
END AS VALUE
can use TRY_TO_DOUBLE which if it fails to parse as a float, will return null.
thus:
,TRY_TO_DOUBLE(Replace(VALUE,'"','')) as value

Dynamic Case Expression Based on Dates

I have a SQL query that has multiple conditions that will change the WHERE clause. I have three case expressions that dynamically update this WHERE clause. The last two case expressions are working well. However, the first one is more dynamic than the last two and I am having issues with it.
Here is the portion of the table that is applicable to this exercise
(Image of Table)
I need it to work as follows:
When my variable #selection = 1, I need it to sort my return based on two dates being passed in.
When my variable #selection = {any other int}, I need it to return all dates.
Query with Description
...
WHERE
{Start Date} = (case when #selection = 1 then {return all values where Start Date is between two dates that are passed in} else {return all Start Dates})
...
Entire Query
DECLARE #selection integer ;
DECLARE #items integer ;
DECLARE #washTypes integer ;
SET #selection = {Root Container.Selection Group.Selection Checkbox.controlValue} ;
SET #items = {Root Container.Items Group.Items Checkbox.controlValue} ;
SET #washTypes = {Root Container.Types of Wash Group.Wash Types Checkbox.controlValue} ;
SELECT
RAW_CIP_records_ndx as 'Index',
start as 'Start',
stop as 'End',
total_duration as 'Total Duration',
item as 'Item',
wash_type as 'Type of Wash',
operator as 'CIP Operator',
program_complete as 'Program Fully Completed?'
FROM RAW_CIP_records
WHERE
start = (case when #selection = 1 then (BETWEEN '{Root Container.Start Date.formattedDate}' and '{Root Container.End Date.formattedDate}') else start end)
and
item = (case when #items = 0 then 'Receiving Bay 1' when #items = 1 then 'Receiving Bay 2' when #items = 2 then 'Receiving Bay 3' else item end)
and
wash_type = (case when #washTypes = 0 then 'Regular' when #washTypes = 1 then 'Sanitize' when #washTypes = 2 then 'Acid' else wash_type end)
I can get a simple WHERE clause to work with these two dates and the BETWEEN function. However, I can't figure out how to pass all of this into a CASE expression.
You could do it a WHERE condition in one query
WHERE (
#selection = 1 AND (start BETWEEN #startDate and #endDate)
OR #selection <> 1
)
But I would suggest you are better off with two separate queries as it will be more likely to use an index.
IF #selection = 1
SELECT ...
ELSE
SELECT ...
Maybe something like this:
WHERE
1 = (case when #selection = 1 then
case when start BETWEEN '{Root Container.Start Date.formattedDate}' and '{Root Container.End Date.formattedDate}' then 1 else 0 end
else 1
end)
and
item = ...
Warning: this will most likely not make use of any indexes, so only use if performance is acceptable in your case.

SQL - Condition to flag more than 1 column is not null

My table has 10 columns. Col1, Col2...Col10
Only one of them should have a numeric value > 0 in it. If more than 1 has a value > 0, then I want to create an error. How can I setup a condition to do that?
Where Col1 is > 0 and Col2 = 0, Col3 = 0, Col4 = 0...
Because there are too many columns, the manual way of writing every scenario is too much code.
What is a more efficient way to do this?
A check constraint to ensure not more than one column has a value greater than zero could look like this:
alter table mytable add constraint check_my_columns
check
(
case when col1 > 0 then 1 else 0 end +
case when col2 > 0 then 1 else 0 end +
case when col3 > 0 then 1 else 0 end +
case when col4 > 0 then 1 else 0 end +
...
<= 1
);
Considering the Cols are type Bit (can hold 0 or 1)
You can sum all the columns and if you get a value > 1 then show the error message
Ex:
if (isnull(col1,0) + isnull(col2,0) + isnull(col3,0) + ... + isnull(col10,0) > 1)
begin
Show error message
Return;
end
You can use apply:
select t.*,
(case when s.col > 2 then 'ERROR' else 'OKAY' end) as status
from t cross apply
(select count(*) as cnt
from (values (t.col1), (t.col2), . . . ) v(col)
where col > 0
) s
You can adjust the where clause to count non-NULL values or whatever.

coalesce and a case statement - explanation?

I'm working on a query that doesn't seem to be doing what it's supposed to since being transferred from one SSRS server to another, and the following line in part of the where statement appears to be where the difference is, or at least from what I can find.
where COALESCE(field, -1) = CASE field WHEN 1 THEN 0 ELSE -1 END
I know it's probably a bit generic but can anyone shed any light on what this may be doing? I've read up on coalesce and gather that it finds the first non-null value from the specified list of fields, but I don't understand what the '-1' does there.
I hope it's not too general a question and that someone can give me a clue as to what it may be doing
Without context it's difficult to give a truly helpful answer.
At first glance it looks as though it could be rewritten much more simply from this:
WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
to this:
WHERE COALESCE(#field, -1) = -1
If that is true then basically you are saying that if the field is null or the field equals -1 then the condition is true otherwise it's false.
Here are some tests to try to prove this:
-- Original
DECLARE #field INT
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = -1
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 0
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 1
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 2
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
SET #field = 3
SELECT 1 WHERE COALESCE(#field, -1) = CASE #field WHEN 1 THEN 0 ELSE -1 END
--Rewritten
DECLARE #field INT
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = -1
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 0
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 1
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 2
SELECT 1 WHERE COALESCE(#field, -1) = -1
SET #field = 3
SELECT 1 WHERE COALESCE(#field, -1) = -1
Both sets of queries in this test give the same results, but as I said without context and realistic test data it's difficult to know if there was a reason why the query was written in the way that it originally was.
Here is another example from a different perspective, using a LEFT JOIN:
DECLARE #MainTable AS TABLE(ident INT)
DECLARE #PossibleNullTable AS TABLE(mainIdent INT, field INT)
INSERT INTO #MainTable(ident) VALUES(1)
INSERT INTO #MainTable(ident) VALUES(2)
INSERT INTO #MainTable(ident) VALUES(3)
INSERT INTO #MainTable(ident) VALUES(4)
INSERT INTO #MainTable(ident) VALUES(5)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(1,-1)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(1,1)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(1,0)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(2,0)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(3,1)
INSERT INTO #PossibleNullTable(mainIdent, field) VALUES(5,-1)
--Original
SELECT *
FROM #MainTable mt
LEFT JOIN #PossibleNullTable pnt
ON mt.ident = pnt.mainIdent
WHERE COALESCE(field, -1) = CASE field WHEN 1 THEN 0 ELSE -1 END
--Original Result
ident mainIdent field
1 1 -1
4 NULL NULL
5 5 -1
--Rewritten
SELECT *
FROM #MainTable mt
LEFT JOIN #PossibleNullTable pnt
ON mt.ident = pnt.mainIdent
WHERE COALESCE(field, -1) = -1
--Rewritten Result
ident mainIdent field
1 1 -1
4 NULL NULL
5 5 -1
Again both queries in this test give the same results.
the first non-null value from the specified list of fields
This means the list of fields between the parenthesis. For instance:
COALESCE(col1,col2,col3,-1)
means that if col1 is not null then use this, else check col2. If col2 is null then check col3. If that is null too then use -1 as the value.
In your example, COALESCE(field, -1) is equivalent to ISNULL(field, -1)
In my example COALESCE(col1,col2,col3,-1) is equivalent to ISNULL(ISNULL(ISNULL(col1, col2), col3), -1)
This is a bit complex expression used in where clause, that suggests
use field column, replace NULL values with -1 & compare all these values of field column with the case expression such as,
here at first, we have to consider that there is no null value in field column as we have replaced all null with -1 using coalesce().
then in case statement, if the values is 1 then it is replace by 0. So 0 is checked with coalesce(field,-1), if it is also 0, then expression is true else false.
Similar for field value -1 using case.

Sql Server Where Case Then Is Null Else Is Not Null

I have a procedure which receive a bit variable called #FL_FINALIZADA.
If it is null or false I want to restrict my select to show only the rows that contain null DT_FINALIZACAO values. Otherwise I want to show the rows containing not null DT_FINALIZACAO values.
Something like this:
SELECT
*
FROM
MyTable
WHERE
...
AND
(
OPE.DT_FINALIZACAO = (
CASE
WHEN (#FL_FINALIZADA <> 1)
THEN NULL
END
) OR
OPE.DT_FINALIZACAO IS NOT NULL
)
In this case I receive the message:
None of the result expressions in a
CASE specification can be NULL.
How can I achieve this?
Thanks in advance.
SELECT
*
FROM
MyTable
WHERE
(ISNULL(#FL_FINALIZADA, 0) = 0
AND
OPE.DT_FINALIZACAO IS NULL
)
OR
(#FL_FINALIZADA = 1
AND
OPE.DT_FINALIZACAO IS NOT NULL
)
Change the AND to be:
AND (((#FL_FINALIZADA <> 1) AND (OPE.DT_FINALIZACAO IS NULL)) OR ( (#FL_FINALIZADA = 1) AND (OPE.DT_FINALIZACAO IS NOT NULL)))
If the bit flag is 1 then DT_FINALIZACAO can't be null.
IF #FL_FINALIZADA IS NULL
SET #FL_FINALIZADA = 0
SELECT * FROM NewsletterSubscribers
WHERE
(#FL_FINALIZADA = 0 AND OPE.DT_FINALIZACAO IS NULL)
OR
(#FL_FINALIZADA = 1 AND OPE.DT_FINALIZACAO IS NOT NULL)
My detailed SQL is a little rusty, but have you tried using 0 insted of NULL? I would expect 0 to evaluate the same as NULL in that select