Fastest T-SQL to convert zeros to NULL in multiple columns - sql-server-2012

We have some large data warehouse tables. Our transformation code makes sure all the numeric measure columns use zero instead of NULL for T-SQL math.
(CASE WHEN NULL or '' then 0)
In the last transformation section we need to turn all the zeros back to NULL for use in Analysis Services MDX. Trying to make sure the No Data lines are not showing in the reports. Previously set to 0 for SQL math because 1 + NULL = NULL in SQL and we want it to equal 1
where as 1 + NULL in Analysis Services = 1.
It is taking about two hours to do the back conversion with individual set statements for each column/measure. I am looking for a way to do it in one read through the table/file instead of thirty-three table scans.
Will the following work and will it be faster?
UPDATE MyTable
SET Col1 = NULLIF(Col1, 0),
Col2 = NULLIF(Col2, 0),
Col3 = NULLIF(Col3, 0)
WHERE (Col1 = 0
OR Col2 = 0
OR Col3 = 0)

How do you know that it will not be fast enough? did you do any bench marking? You can as well use CASE condition like below but per MSDN Spec both are same. Which states that:
NULLIF is equivalent to a searched CASE expression in which the two
expressions are equal and the resulting expression is NULL.
UPDATE MyTable
SET Col1 = CASE WHEN Col1 = 0 THEN NULL END,
Col2 = CASE WHEN Col2 = 0 THEN NULL END,
Col3 = CASE WHEN Col3 = 0 THEN NULL END
WHERE (Col1 = 0 OR Col2 = 0 OR Col3 = 0)

Related

How can I use consecutive conditional clause in SQL?

I was trying to work with CASE WHEN in Postgresql in order to evaluate something and then do another thing. However, I need not only to check two things but they must be checked in consecutive order.
Example, let's say I have 3 columns: col1, col2 and col3.
I want to check first if col1 is greater than 0. After checking this I want to check if col2 is greater than 0. If that's the case, I will create another column which will be the sum of all of them. However, I can't do this:
select case when col1>0 and col2>0 then col1+col2+col3 end as...
I need to do something like this:
select case when col1>0 then (case when col2>0 then col1+col2+col3) else NULL end as...
But that doesn't work. So, what can I do?
You were close. You can do:
select
case when col1 > 0 then case when col2 > 0 then col1 + col2 + col3 end
else NULL end as my_column1
You had missed the inner end.
By the way, a CASE expression evaluates to NULL when no when clause is matched. Therefore, else NULL is redundant.

How do I update a row to be valid if the other columns match a certain DataType?

I have a table with 5 rows. An ID column, 2 varchar columns, an isValid Column and a ValidationFailure column. The data for 2 columns are updated with data from an excelsheet through code. The data types while inserting for 2 columns are varchar. I now have to check if these 2 columns match MONEY type and if there is an issue update column isValid to false with ValidationFailure column a concatenation of the column names that fail the test.
I am using an update statement with a where clause. But I am unable to have a concatenation of the column names that fail the condition.
I am using the following update statement :
update t
set t.isValid = 0
from table t
where IsNumeric(t.col1+'e0') = 0 or IsNumeric(t.col2+'e0') = 0
How can I update t.ValidationFailure column with the column names that failed the condition?
If both fails then the column value can be col1,col2
This can be achieved with a CASE
update t set
t.isValid = 0,
t.ValidationFailure =
case
when IsNumeric(t.col1+'e0') + IsNumeric(t.col2+'e0') = 0 then 'both'
when IsNumeric(t.col1+'e0') = 0 then 'col1'
when IsNumeric(t.col2+'e0') = 0 then 'col2'
else 'unknown'
end
from table t
where IsNumeric(t.col1+'e0') = 0
or IsNumeric(t.col2+'e0') = 0

How to get an index used with OR in statement

I have SQL with params passed by user. User can pass some id or -1, what mean "nevermind".
It's possible to write query like below, but can using index?
SELECT *
FROM table
WHERE
((col1 = :param1) OR (:param1 = -1))
AND ((col2 = :param2) OR (:param2 = -1))
AND col3 STARTING 'A'
col1, col2 and col3 are indexed. In FB 2.x using OR never use index for col1 or col2. In FB 3 only if first (or second) conditions exist that can use index (PLAN index and natural), but with last condition stop using index for col1/2.
How can I write SQL without using PLAN and can use index for col1/2 and stay possibility to "off" condition by passing -1?
You can rewrite a condition like
(col1 = :param1) OR (:param1 = -1)
as
col1 = case when :param1 = -1 then col1 else :param1 end
Since it's a single expression, you can also safely delete all the brackets, which makes the query easier to read.

SQL - Select only one value from multiple fields

Assume the following
col1 col2 col3 col4
------+----------+---------+---------
abc | | |
Yes, col1-4 have a space in them!
I want to select the column that is not a space . On row 1 it's col1, but on row 20 it may be col3, row 55 it may be col2, and so on. I need to return just that column.
There will always be only one column with a stored value within this range of four columns, I just need the one that actually has information in it.
This will be part of a greater query for a report, so regardless of what column abc is in I need that to look the same in every result case. Meaning I can't have the results be col1 for one case and col2 for the other because the report won't recognize. The column needs to always be called the same.
Yes, I know it's better to store NULLS versus spaces and why use four columns when only one can have data, why not use one. I've complained enougth about that so don't rip me a new one about bad db design because I AGREE.
SELECT LTRIM(RTRIM(col1 + col2 + col3 + col4))
Here we go... Why not add bad code to bad design. You could technically add all of the columns together and then trim them for leading/trailing spaces. I don't recommend it for performance on large scale deployments. Heck, I don't recommend this for any production script but I've been here before... Gotta do what you can to get it done.
Why not use a CASE statement, like
CASE WHEN col1 <> ' ' THEN col1
WHEN col2 <> ' ' THEN col2
WHEN col3 <> ' ' THEN col3
WHEN col4 <> ' ' THEN col4
END
You can do this:
case
when col1 != '' then col1
when col2 != '' then col2
...
end

How can I assign one field's value to another field based on a third field?

I have three fields and if column three equals a certain value, I want to get the value of column 2. Can I do this in a SELECT, and would I use an IF or CASE statement?
A CASE statement would be the easiest way to do this. The following SQL compares two columns. You can alter this to use WHEN Col2 = 'xxxx' THEN xxxx'.
SELECT Col1, Col2, CASE
WHEN Col2 = Col1 THEN 'True'
ELSE 'False'
END AS 'Columns Match'
FROM Table
Hope this leads you in the right direction
Select
Case
when columnthree = 'VALUE'
then column2
else 'do something'
end as [column name]
from
table name
Also you might want to do some conversion if the datatypes for both columns are different
You could use a CASE clause within a SELECT statement - IF won't work this way in SQLServer.
select Alpha, Beta, Gamma,
case
when Alpha > 2 * Beta then Gamma
when Beta = Gamma then Alpha + 3
when Gamma = 2 then 13
else 42
end as 'Omega'
from Alphabet
First match wins.
CASE returns a value, so it may be helpful in various circumstances:
delete ... where case when Id > Limit then 1 else 0 end = 1
update ... set ShoeSize = case when Wide = 1 then ShoeSize + 1 else ShoeSize end, ...