Converting Excel Formula involving *OR to TSQL - sql-server

I'm trying to convert this formula into T-SQL.
=IF(D6>F6,D6-C6-1,F6-C6-1)*OR(IF(F6-C6-1<0,0,F6-C6-1))
Does anyone know what the *OR actually means?
The columns C, D, F are all Date fields.
For example
For the first line, this part of the formula IF(D6>F6,D6-C6-1,F6-C6-1) returns 35 and the second part of the formula IF(F6-C6-1<0,0,F6-C6-1) returns 35 as well. So shouldn't the result be 35 x 35 = 1225. The correct answer is 35 however.

As per my earlier comment:
The second parameter in the OR would be optional. As a matter of fact, or will just return 'TRUE' if any of it's paramaters is 'TRUE', no matter the amount of (optional) parameters you use. The 'OR' in this case just evaluates the outcome of the second 'IF' (which is 35). So > 'OR(35)' which evaluates to TRUE. Since you multiply this will again evaluate to '35*1' being your final result. The formula is looking strange because 'OR' would always return true in this case. The formula might as well just be '=IF(D6>F6,D6-C6-1,F6-C6-1)'

Related

Compare and divide in report builder

I have a condition I want to divide two values in report builder with same date but different sample name in the same table...
For example, in this image, I want to divide the CM2(2.85) and Raw Meal(0.58) value. their result should be 4.9.
And if these two parameters (CM2 and Raw Meal) are not on the same date then the value should be empty or nothing. Please help I am new to report builder expression.
I've tried this expression but it does not give me what I need
IIf(InStr(Fields!Sample_Code.Value,"CM2") > 0, Fields!So3.Value, nothing) / IIf(InStr(Fields!Sample_Code.Value,"Raw Meal") > 0, Fields!So3.Value, nothing)
The record will either be CM2 or Raw Meal, but it will never contain both at the same time. If Fields!Sample_Code.Value = "CM2" is true, the second half of the expression will be false, or vice-versa. Fields!Sample_Code.Value can't be two different values at the same time, it can only contain the data from a single record.
Your expression will result in either:
nothing/Fields!So3.Value
or
Fields!So3.Value/nothing.
As a simplified example:
IF( x=1 , 1 , null) / IF( x=2 , 1 , null)
X cannot be two different values at the same time so the expression will never return a non-null result.
You'll need to join CM2 and RAW MEAL records together to evaluate them at the same time. That would probably require a significant change to what you've posted so far.

Get the complete number when divide two fields

I was trying to round some fields. When I have 59 days, I want to change it to 60.
The problem is that when I use this code, the 59 is changed to 30 because the round it is 1.
select round(1.9666,0)*30, round(59/30,0)*3'
The result of that query is 60 for the first field and 30 for the second one. The problem is that when I've tried:
select 59/30
The result is 1 and I need the entire answer that is 1.9666...
How can I make it?
Because the number you are dividing by is an INT (the data type of the left side is irrelevant), SQL Server will return an INT as the answer.
If you want a number with a decimal place as your result, you'll need to divide by one.
Don't cast to a FLOAT as the answer is probably not what you want (floats are generally not accurate and are 'approximations'):
SELECT 59 / CAST(30 AS FLOAT) -- = 1.96666666666667
CAST the right-hand side of the division to a DECIMAL:
SELECT 59 / CAST(30 AS DECIMAL(10, 2)) -- = 1.96666
SELECT cast(59 AS FLOAT) / cast(30 AS FLOAT)
Because the original figures are whole numbers, SQL presumes you want a whole number output.
To ensure you get one with the decimal places, you need to first change the data type from an integer int to a floating point float.
This is what the CAST command does.
EDIT: Commenter suggests you cast to DECIMAL instead. The principle is the same, but you need to supply more arguments. To cast to a decimal use something like:
cast(59 as DECIMAL(18, 3))
The first argument (the 18) is the total number of figures you want to permit in the decimal. The second argument (the 3) is the number you want after the decimal point.
The suggestion that it's more accurate is correct - as you'll see if you run the SELECT statements in this answer one after the other. But in this particular case, it only makes a tiny difference.

Select then parse using substring and cast gives different result from computation

I parsed a string which I use substring to get the last 11 i think numbers of characters. I accomplished that one but when I use cast and round it gives a different result from the manual computation I did.
Here's my query
SELECT round(cast(SUBSTRING('351856040520298,241111;1R,141117003059,A,1420.4629N,12058.7028E,0.0,77,0.9,20000006;2R,141117003059,11,98.3,12.58,04.10,282098820.9', 123,11)as float)/3600, 0, 1)
This gives me a result of 583. But when I try to manually compute using the computation below
282098820.9 / 3600
The result is
78360.7835
Is there something wrong with my query?
Thanks for the help.
The problem is with your SUBSTRING. It only returns 2098820.9 instead of 282098820.9. Try using RIGHT to extract the last 11 characters.
SELECT round(cast(right('351856040520298,241111;1R,141117003059,A,1420.4629N,12058.7028E,0.0,77,0.9,20000006;2R,141117003059,11,98.3,12.58,04.10,282098820.9', 11)as float)/3600, 0, 1)

Postgres NOT in array

I'm using Postgres' native array type, and trying to find the records where the ID is not in the array recipient IDs.
I can find where they are IN:
SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))
But this doesn't work:
SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3 = NOT ANY (recipient_ids))
What's the right way to test for this condition?
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))
You can always negate WHERE (condition) with WHERE NOT (condition)
You could turn it around a bit and say "3 is not equal to all the IDs":
where 3 != all (recipient_ids)
From the fine manual:
9.21.4. ALL (array)
expression operator ALL (array expression)
The right-hand side is a parenthesized expression, which must yield an array value. The left-hand expression is evaluated and compared to each element of the array using the given operator, which must yield a Boolean result. The result of ALL is "true" if all comparisons yield true (including the case where the array has zero elements). The result is "false" if any false result is found.
Beware of NULLs
Both ALL:
(some_value != ALL(some_array))
And ANY:
NOT (some_value = ANY(some_array))
Would work as long as some_array is not null. If the array might be null, then you must account for it with coalesce(), e.g.
(some_value != ALL(coalesce(some_array, array[]::int[])))
Or
NOT (some_value = ANY(coalesce(some_array, array[]::int[])))
From the docs:
If the array expression yields a null array, the result of ANY will be null
If the array expression yields a null array, the result of ALL will be null
Augmenting the ALL/ANY Answers
I prefer all solutions that use all or any to achieve the result, appreciating the additional notes (e.g. about NULLs). As another augementation, here is a way to think about those operators.
You can think about them as short-circuit operators:
all(array) goes through all the values in the array, comparing each to the reference value using the provided operator. As soon as a comparison yields false, the process ends with false, otherwise true. (Comparable to short-circuit logical and.)
any(array) goes through all the values in the array, comparing each to the reference value using the provided operator. As soon as a comparison yields true, the process ends with true, otherwise false. (Comparable to short-circuit logical or.)
This is why 3 <> any('{1,2,3}') does not yield the desired result: The process compares 3 with 1 for inequality, which is true, and immediately returns true. A single value in the array different from 3 is enough to make the entire condition true. The 3 in the last array position is prob. never used.
3 <> all('{1,2,3}') on the other hand makes sure all values are not equal 3. It will run through all comparisons that yield true up to an element that yields false (the last in this case), to return false as the overall result. This is what the OP wants.
an update:
as of postgres 9.3,
you can use NOT in tandem with the #> (contains operator) to achieve this as well.
IE.
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids #> ARRAY[3];
not (3 = any(recipient_ids))?
Note that the ANY/ALL operators will not work with array indexes. If indexes are in mind:
SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids
and the negative:
SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)
An index can then be created like:
CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)
Use the following query
select id from Example where NOT (id = ANY ('{1, 2}'))

Is SQL Server's double checking needed here?

IF #insertedValue IS NOT NULL AND #insertedValue > 0
This logic is in a trigger.
The value comes from a deleted or inserted row (doesn't matter).
2 questions :
Do I need to check both conditions? (I want all value > 0, value in db can be nullable)
Does SQL Server check the expression in the order I wrote it ?
1) Actually, no, since if the #insertedValue is NULL, the expression #insertedValue > 0 will evaulate to false. (Actually, as Martin Smith points out in his comment, it will evaluate to a special value "unknown", which when forced to a Boolean result on its own collapses to false - examples: unknown AND true = unknown which is forced to false, unknown OR true = true.) But you're relying on comparison behaviour with NULL values. A single step equivalent method, BTW, would be:
IF ISNULL(#insertedValue, 0) > 0
IMHO, you're better sticking with the explicit NULL check for clarity if nothing else.
2) Since the query will be optimised before execution, there is absolutely no guarantee of order of execution or short circuiting of the AND operator.
Combining the two - if the double check is truly unnecessary, then it will probably be optimised out before execution anyway, but your SQL code will be more maintainable in my view if you make this explicit.
You can use COALESCE => Returns the first nonnull expression among its arguments.
Now you can make the query more flexible, by increasing the column limits and again you need to check the Greater Then Zero condition. Important point to note down here is you have the option to check values in multiple columns.
declare #val int
set #val = COALESCE( null, 1, 10 )
if(#val>0)
select 'fine'
else
select 'not fine'

Resources