DRY for field formula in Oracle SQL - sql

We have some SQL in Oracle which looks like this:
SELECT
CASE
WHEN
field1 - field2 + field3 < 0
THEN
0
ELSE
field1 - field2 + field3
END
we'd like to specify field1 - field2 + field3 once, whilst not altering the output of the SELECT query. Is there any neat way to do this?
As an alternative, if there is a function which can return a numeric value above 0 and returns 0 for negative values that would work as well.

Use greatest():
select greatest(field1 - field2 + field3, 0)

Something like this. If you wrap it in a stored procedure you can return the result.
DECLARE
n number := field1 - field2 + field3;
BEGIN
CASE
WHEN
n < 0
THEN
0
ELSE
n
END CASE
END;

Try:
SELECT
CASE
WHEN
expr < 0
THEN
0
ELSE
expr
END
FROM (SELECT field1 - field2 + field3 as expr
FROM ... );

Related

Selecting a specific value within a case statement

I need help with selecting a specific value within a CASE Statement.
For an example
SELECT CASE WHEN Field1 >= (Field2 = 1) THEN Answer
WHEN Field1 < (Field2 = 1) THEN No Answer
ELSE Question END AS Field3
I want to be able to select a specific value in Field2 within the CASE Statement
could be you are looking for
SELECT CASE WHEN Field1 >= Field2 AND Field2 = 1 THEN Answer
WHEN Field1 < Field2 AND Field2 = 1 THEN No Answer
ELSE Question END AS Field3
or more simply
SELECT CASE WHEN Field1 >= 1 THEN Answer
WHEN Field1 < 1 THEN No Answer
ELSE Question END AS Field3
-- 1. You don't specify the fields types.
-- 2. You do a comparison of Field1 with a logical expression (Field2=1). i guess it fails.
-- 3. I will assume Answer, No answer and Question will be the desired string result, and have to be quoted.
-- 4. A Table name is missing. I will assume Field1 and Field2 are fields from MyTable
-- 5. I' am assuming Field1 and Field2 of the same type, and be varchar(10) for example.
DECLARE #Field2 varchar(10) = 1
SELECT
CASE WHEN Field1 >= Field2 THEN 'Answer'
WHEN Field1 < Field2 THEN 'No Answer'
ELSE 'Question'
END AS Field3
FROM MyTable
WHERE Field2 = #Field2

stored procedure issue using fields from the #temp table

I have a stored procedure that basically does this:
Create table #temp(
field1 int,
field2 int,
total int,
total2 int,
total3 int
)
insert into #temp
(
field1,
field2,
)
Select x.field1, y.field2 from tblA x left join tblB y on x.clientid = y.clientid
This works great, this is very much simplified.
Now what I'm doing is UPDATING values for Total, Total2 and Total3 like so:
update #temp set Total = field1 + field2 <-- works
total2 = field1 + field2 + 300 <-- works
total3 = total2 * 100.0 <-- no value
So here in the update statement above, if I use the field that had already been inserted into the table, they let me UPDATE it, however, since I updated total2 in the table, I am unable to use it in total3? Any idea why?
The totals columns are NULL at the time you run the update.
So total3 is doing this: NULL * 100.0
You can either update total3 separately, once you've populated total2:
update #temp
set total = field1 + field2,
total2 = field1 + field2 + 300
update #temp
set total3 = total2 * 100.0
Or you can replace total2 with the logic that populates it:
update #temp
set total = field1 + field2,
total2 = field1 + field2 + 300,
total3 = (field1 + field2 + 300) * 100.0
This is your update:
update #temp
set Total = field1 + field2 <-- works
total2 = field1 + field2 + 300 <-- works
total3 = total2 * 100.0 <-- no value
You have only set values for field1 and field2, so the other values are empty. You need to understand that the set clause is executed "all-at-once" not sequentially. Column references on the left of the = are the "new" record; column references on the right are the "old" record. Hence, you can solve the problem by repeat the expression.
Another way to solve the problem is to use a subquery, CTE, or apply:
update #temp
set Total = v.new_total,
total2 = v2.new_total2 <-- works
total3 = v2.total2 * 100.0 <-- no value
from #temp t cross apply
(values (field1 + field2) ) v(new_total),
(values (new_total + 300) ) v2(new_total2)
May be try the following:
update #temp set Total = field1 + field2
total2 = field1 + field2 + 300
total3 = (field1 + field2 + 300) * 100.0
The problem you are having is because the total2 variable is being set at the same time you are attempting to access it. In order to make the update work correctly you must update total3 with the same logic used to update total2 OR you have to create a separate update for total3.
This is how I would do it:
update #temp set Total = field1 + field2 <-- works
total2 = field1 + field2 + 300 <-- works
total3 = (field1 + field2 + 300) * 100.0 <-- should get value
Notice that I put the addition logic for total2 in the paranthesis used to calculate total3. This is because the total2 variable holds no value until the statement completes execution.
The alternative is to split the update into 2 separate statments such as this:
update #temp set Total = field1 + field2 <-- works
total2 = field1 + field2 + 300 <-- works
and then
update #temp set total3 = (field1 + field2 + 300) * 100.0

SQL Inequality in CASE WHEN statement not working due to NULL values

I have a SQL query which includes the following statement
SELECT
(CASE
WHEN field1 > 0 THEN field1
ELSE (field2 * field3)
END) AS result
FROM table
Which is supposed to return the value of field1, unless that is '0', in which case the statement returns the product of two other fields.
The issue I am having is this statement returns NULL if field1 is NULL.
I want to revise my SQL so that the product of fields 2 & 3 is returned when field1 is NULL, just as it does when field1 is '0'.
I have tried the following:
SELECT
(CASE
WHEN field1 > 0 THEN field1
WHEN field1 IS NULL THEN (field2 * field3)
ELSE (field2 * field3)
END) AS result
FROM table
But NULL still seems to permeate through the statement and NULL is still being returned whenever field1 is NULL.
Your query does already what you want. When field1 is NULL, it returns the product field2 * field3. If either of field2 or field3 though is NULL, the (returned) product will be NULL.
If you want to be returning some value (0 perhaps) when either of them is NULL, you can change the CASE:
SELECT
(CASE
WHEN field1 > 0 -- when field1 > 0
THEN field1
WHEN field2 IS NULL OR field3 IS NULL -- when field1 = 0 or NULL
THEN 0
ELSE field2 * field3
END) AS result
FROM table ;
or simply:
SELECT
(CASE
WHEN field1 > 0
THEN field1
ELSE COALESCE(field2 * field3, 0)
END) AS result
FROM table ;
You can use COALESCE / IFNULL (SQL Server / MySQL)
Easy as:
SELECT
COALESCE((CASE
WHEN field1 > 0 THEN field1
ELSE (field2 * field3)
END), 0) AS result
FROM table
To help you diagnose this issue, use something like this:
SELECT
(CASE
WHEN field1 > 0 THEN field1
WHEN field1 IS NULL THEN (field2 * field3)
ELSE (field2 * field3)
END) AS result,
field1, field2, field3
FROM table
WHERE
(CASE
WHEN field1 > 0 THEN field1
WHEN field1 IS NULL THEN (field2 * field3)
ELSE (field2 * field3)
END) IS NULL
It will become immediately apparrent what the problem is.

SQL update, string to numeric

In an SQL Server database, I have to update some fields, the query is (, is the decimal separator) :
UPDATE MyTbable
SET
Field1 = CAST('111,11' AS DEC(18,4)),
Field2 = CAST('222,22' AS DEC(18,4)),
Field3 = CAST('333,33' AS DEC(18,4))
WHERE Id = '1'
I receive the error :
Error converting data type varchar to numeric. I tried with the cast, same problem
Field1,Field2 and Field3 are numeric 38,2
Any idea ?
Thanks,
Take the commas out.
UPDATE MyTbable
SET
Field1 = CAST(REPLACE('111,11',',','.') AS DEC(18,4)),
Field2 = CAST(REPLACE('222,22',',','.') AS DEC(18,4)),
Field3 = CAST(REPLACE('333,33',',','.') AS DEC(18,4))
WHERE Id = '1'
Use . instead of ,
UPDATE MyTbable
SET
Field1 = CAST('111.11' AS DEC(18,4)),
Field2 = CAST('222.22' AS DEC(18,4)),
Field3 = CAST('333.33' AS DEC(18,4))
WHERE Id = '1'
If you want to select these values afterwards as string and with comma then do that:
select replace(cast(Field1 as varchar(30)), '.',','),
replace(cast(Field2 as varchar(30)), '.',','),
replace(cast(Field2 as varchar(30)), '.',','),
where Id = '1'
remove the commas in you query like :
UPDATE MyTbable
SET
Field1 = CAST('11111' AS DEC(18,4)),
Field2 = CAST('22222' AS DEC(18,4)),
Field3 = CAST('33333' AS DEC(18,4))
WHERE Id = '1'
or you can rmove the comma using replace:
replace('111,11',',','.')

Conditional statement in WHERE clause

I need to write a conditional statement in my where clause that uses different operators based on the parameter passed into the procedure. I can't seem to find the syntax that will work.
My example is as follows:
#DateValue datetime
select *
from table
where field1 = 'x'
and field2 = 'y'
and if #DateValue = '1/1/1900' then
field3 <= getdate()
else
field3 = #DateValue
end
Thanks for everyone's assistance.
and ((#DateValue = '1/1/1900' and field3 <= getdate()) or
(#DateValue <> '1/1/1900' and field3=#DateValue))
I think you would need something like (psuedo-code)
Create PROCEDURE GetPartialTable
#DateValue datetime
AS
Begin
IF (#DateValue = '1900-01-01')
select * from table where field1 = 'x' and field2 = 'y' and field3 <= getdate();
else
select * from table where field1 = 'x' and field2 = 'y' and field3 = #DateValue;
END IF
END
It sounds like the solution above, but the results might be seriously different if the context is more general, e.g. if the entire SQL statement is completely different.