How to combine two nullable boolean fields in SQL - sql

I have these fields :
ISNULL(
dbo.Features.TheifAlarm,
0
) AS ExtraTheifAlarm,
ISNULL(
dbo.Features.FireAlarm,
0
) AS ExtraFireAlarm,
dbo.Features.TheifAlarm and dbo.Features.FireAlarm are nullable bits. But I'm using EntityFramework and they are nullable boolean in my model. I want to combine them with OR.
This is my attempt :
ISNULL(
dbo.Features.TheifAlarm,
0
)
OR
ISNULL(
dbo.Features.FireAlarm,
0
)
But it didn't work, how can I combine these two columns? Thanks in advance

To 'combine' two fields you can use bitwise operators.
In your case (in the SELECT list):
SELECT (ISNULL(col1, 0) | ISNULL(col2, 0)) AS combinedCol FROM ...
Or as a WHERE condition:
SELECT ... WHERE (ISNULL(col1, 0) = 1 OR ISNULL(col2, 0) = 1)
Actually you don't even need the ISNULL() in the WHERE condition (col1 = 1 evaluates to FALSE (ok, NULL, but treated as FALSE) when col1 is null):
SELECT ... WHERE (col1 = 1 OR col2 = 1)
Edit: Just to add some alternatives:
Simple addition
SELECT IIF((ISNULL(col1, 0) + ISNULL(col2, 0)) > 0, 1, 0)
CASE..WHEN structure (as iamdave mentioned)
SELECT CASE WHEN col1 = 1 THEN 1 ELSE IIF(col2 = 1, 1, 0) END
Another CASE..WHEN
SELECT CASE WHEN (col1 = 1 OR col2 = 1) THEN 1 ELSE 0 END
or with IIF
SELECT IIF(col1 = 1 OR col2 = 1), 1, 0)

I am assuming you want to return a true if either field is true?
If so, you can check for both with a case:
select case when ISNULL(dbo.Features.TheifAlarm,0) = 0 -- If the first is False
then ISNULL(dbo.Features.FireAlarm,0) -- Return the value of the second
else 1 -- Otherwise return True
end as EitherAlarmCheck
If you are looking to filter your dataset for one of these values being True, you can use an OR in your where clause:
select Cols
from Table
where ISNULL(dbo.Features.TheifAlarm,0) = 1
or ISNULL(dbo.Features.FireAlarm,0) = 1

Related

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.

SQL - want to write unique error value per IF condition

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

A SQL query to count how many attributes a record has in common with another record?

I am trying to write a SQL query to take the count of columns with equal value in my schema for each row by comparison to a single record.
Example:
record1: 1, 0, 1, 0, 0
record2: 0, 0, 0, 0, 1
record3: 0, 0, 1, 0, 0
record1 has 2 attributes in common with record2, go through the entire table and order by number of attributes each record has in common with record1
Is there a way to write a SQL statement that will do this? I have only found ways to compare each row and specify which attributes must be of equal value.
You can do:
select t.*,
((case when t.col1 = t1.col1 then 1 else 0 end) +
(case when t.col2 = t1.col2 then 1 else 0 end) +
(case when t.col3 = t1.col3 then 1 else 0 end) +
. . .
) as num_in_common
from t cross join
t t1
where t1.id = 1; -- or however you define "record1"
order by num_in_common desc;
Here's a nice routine you can use in SQL Server that will do this if you'd like. Replace #temp with your table name:
declare #holding table (id int, col1 int, col2 int, col3 int, col4 int, col5 int, num_in_common int)
declare #iterator int = 1
declare #row1col1 int, #row1col2 int, #row1col3 int, #row1col4 int ,#row1col5 int
while #iterator<=(select max(id) from #temp)
begin
if #iterator=1
select #row1col1=col1, #row1col2=col2, #row1col3=col3, #row1col4=col4 ,#row1col5=col5
from #temp where id=#iterator
else
insert #holding
select *, case when col1-#row1col1 = 0 then 1 else 0 end +
case when col2-#row1col2 = 0 then 1 else 0 end +
case when col3-#row1col3 = 0 then 1 else 0 end +
case when col4-#row1col4 = 0 then 1 else 0 end +
case when col5-#row1col5 = 0 then 1 else 0 end
from #temp where id=#iterator
set #iterator=#iterator+1
end
select * from #holding

Choose multiple cases condition

I want to get multipule choises after then in case statment as
#value
select * from [dbo].[Currency_Tbl]
WHERE [Currency_Active_YN]=
CASE WHEN #value = 1 THEN
( 1 or 0)
ELSE
#Value = 0 then 0
END
it didn't accept the first line in col1 but accept the col2
how can I select multiple numbers after THEN?
You don't use case in where clauses. Use boolean logic
select * from [dbo].[Currency_Tbl]
WHERE (#value = 1 and [Currency_Active_YN] in (0,1))
OR (#value = 0 and [Currency_Active_YN] = 0)
You dont need a case to do what you're trying to do. Assuming Currency_Active_YN is a not null bit field the following logic should suffice.
select * from [dbo].[Currency_Tbl]
WHERE (#value=1 OR [Currency_Active_YN]=#Value)

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