SQL 'between' vs. comparing both ends - sql

as far as I know, in SQL,
X between Y and Z
gives the same result as
X >= Y and X <= Z
But I often see the latter from people I believe to be SQL experts.
Is there a subtle difference that I should know about?

Great question. In a nutshell, they are essentially the same. Documentation says:
expr BETWEEN min AND max
If expr is greater than or equal to min and expr is less than or equal to max, BETWEEN returns 1, otherwise it returns 0. This is equivalent to the expression (min <= expr AND expr <= max) if all the arguments are of the same type. Otherwise type conversion takes place according to the rules described in Section 12.2, “Type Conversion in Expression Evaluation”, but applied to all the three arguments.
reference: https://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_between

I believe the between syntax is not ANSI compliant, so it is not implemented in all databases. The most common one >= and <= can be used everywhere.

Related

SSIS precedence constraint - expression with AND

I'm using Visual Studio 2019 and SQL Server SSIS.
In a precedence constraint, how do I use an AND within the expression?
For example if I have:
#myVariable1 == 0 AND #myVariable2 == 0
I get the message
Expression cannot be evaluated
This is what I am trying to achieve:
I know the double pipe operator is a logical OR, is there something similar for AND?
you need to use && like so
#myVariable1 == 0 && #myVariable2 == 0
here is complete list of SSIS expression operators:
Operator
Description
Cast
Converts an expression from one data type to a different data type.
() (Parentheses)
Identifies the evaluation order of expressions.
+ (Add) (SSIS)
Adds two numeric expressions.
+ (Concatenate)
Concatenates two expressions.
- (Subtract)
Subtracts the second numeric expression from the first one.
- (Negate)
Negates a numeric expression.
* (Multiply)
Multiplies two numeric expressions.
/ (Divide)
Divides the first numeric expression by the second one.
% (Modulo)
Provides the integer remainder after dividing the first numeric expression by the second one.
|| (Logical OR)
Performs a logical OR operation.
&& (Logical AND)
Performs a logical AND operation.
! (Logical NOT)
Negates a Boolean operand.
| (Bitwise Inclusive OR)
Performs a bitwise OR operation of two integer values.
^ (Bitwise Exclusive OR)
Performs a bitwise exclusive OR operation of two integer values.
& (Bitwise AND)
Performs a bitwise AND operation of two integer values.
~ (Bitwise NOT)
Performs a bitwise negation of an integer.
== (Equal)
Performs a comparison to determine if two expressions are equal.
!= (Unequal)
Performs a comparison to determine if two expressions are not equal.
> (Greater Than)
Performs a comparison to determine if the first expression is greater than the second one.
< (Less Than)
Performs a comparison to determine if the first expression is less than the second one.
>= (Greater Than or Equal To)
Performs a comparison to determine if the first expression is greater than or equal to the second one.
<= (Less Than or Equal To)
Performs a comparison to determine if the first expression is less than or equal to the second one.
? : (Conditional)
Returns one of two expressions based on the evaluation of a Boolean expression.

Why is SQL Server changing operation order and boxing the way it does?

Four simple SELECT statements:
SELECT 33883.50 * -1;
SELECT 33883.50 / -1.05;
SELECT 33883.50 * -1 / 1.05;
SELECT (33883.50 * -1) / 1.05;
But the results are not as I would expect:
-33883.50
-32270.000000
-32269.96773000
-32270.000000
That third result is the one that seems questionable. I can see what is happening, first SQL Server evaluates this:
SELECT -1 / 1.05;
Getting an answer of:
-0.952380
Then it takes that answer and uses it to perform this calculation:
SELECT 33883.50 * -0.952380;
To get the (wrong) answer of:
-32269.96773000
But why is it doing this?
In your example
33883.50 * -1 / 1.05
is evaluated as
33883.50 * (-1 / 1.05)
instead of
(33883.50 * -1) / 1.05
which results in a loss in precision.
I played a bit with it. I used SQL Sentry Plan Explorer to see the details of how SQL Server evaluates expressions. For example,
2 * 3 * -4 * 5 * 6
is evaluated as
((2)*(3)) * ( -((4)*(5))*(6))
I'd explain it like this. In T-SQL unary minus is made to be the same priority as subtraction, which is lower than multiplication. Yes,
When two operators in an expression have the same operator precedence
level, they are evaluated left to right based on their position in the
expression.
, but here we have an expression that mixes operators with different priorities and parser follows these priorities to the letter. Multiplication has to go first, so it evaluates 4 * 5 * 6 at first and then applies unary minus to the result.
Normally (say in C++) unary minus has higher priority (like bitwise NOT) and such expressions are parsed and evaluated as expected. They should have made unary minus/plus same highest priority as bitwise NOT in T-SQL, but they didn't and this is the result. So, it is not a bug, but a bad design decision. It is even documented, though quite obscurely.
When you refer to Oracle - that the same example works differently in Oracle than in SQL Server:
Oracle may have different rules for operator precedence than SQL Server. All it takes is to make unary minus highest priority as it should.
Oracle may have different rules for determining result precision and scale when evaluating expressions with decimal type.
Oracle may have different rules for rounding intermediate results. SQL Server "uses rounding when converting a number to a decimal or numeric value with a lower precision and scale".
Oracle may be using completely different types for these kind of expressions, not decimal. In SQL Server "a constant with a decimal point is automatically converted into a numeric data value, using the minimum precision and scale necessary. For example, the constant 12.345 is converted into a numeric value with a precision of 5 and a scale of 3."
Even definition of decimal may be different in Oracle. Even in SQL Server "the default maximum precision of numeric and decimal data types is 38. In earlier versions of SQL Server, the default maximum is 28."
Do you know BODMAS rule. The answer is correct its not because of Sql Server, Its a basic mathematics.
First comes Division then comes the Subtraction, So always Division will happen before Subtraction
If you want to get correct answer then use proper parenthesis
SELECT (33883.50 * -1) / 1.05;
T-SQL has an rule for operator precedence which it follows. You can read about it on the link https://msdn.microsoft.com/en-us/library/ms190276.aspx.
It seems to be a precedence rule concerning unary operators. I have tried the following queries
SELECT 33883.50 * cast(-1 as int) / 1.05;
SELECT 33883.50 * (-1 * 1) / 1.05;
and it returns the right answer. The best thing to do is to use parentheses on expressions you want to occur first, and test thoroughly.

The parentheses rules of PostgreSQL, is there a summarized guide?

In Mathematics and many programming languages (and I think standard SQL as well), parentheses change precedence (grouping parts to be evaluated first) or to enhance readability (for human eyes).
Equivalent Examples:
SELECT array[1,2] #> array[1]
SELECT (array[1,2]) #> array[1]
SELECT array[1,2] #> (array[1])
SELECT ((array[1,2]) #> (array[1]))
But SELECT 1 = ANY array[1,2] is a syntax error (!), and SELECT 1 = ANY (array[1,2]) is valid. Why?
OK, because "the manual says so". But what the logic for humans to remember all exceptions?
Is there a guide about it?
I do not understand why (expression) is the same as expression in some cases, but not in other cases.
PS1: parentheses are also used as value-list delimiters, as in expression IN (value [, ...]). But an array is not a value-list, and there does not seem to be a general rule in PostgreSQL when (array expression) is not the same as array expression.
Also, I used array as example, but this problem/question is not only about arrays.
"Is there a summarized guide?", well... The answer is no, so: hands-on! This answer is a Wiki, let's write.
Summarized guide
Let,
F() a an usual function. (ex. ROUND)
L() a function-like operator (ex. ANY)
f a operator-like function (ex. current_date)
Op an operator
Op1, Op2 are distinct operators
A, B, C values or expressions
S a expression-list, as "(A,B,C)"
The rules, using these elements, are in the form
rule: notes.
"pure" mathematical expressions
When Op, Op1, Op2 are mathematical operators (ex. +, -. *), and F() is a mathematical function (ex. ROUND()).
Rules for scalar expressions and "pure array expressions":
A Op B = (A Op B): the parentheses is optional.
A Op1 B Op2 C: need to check precedence.
(A Op1 B) Op2 C: enforce "first (A Op1 B)".
A Op1 (B Op2 C): enforce "first (B Op2 C)".
F(A) = (F(A)) = F((A)) = (F((A))): the parentheses are optional.
S = (S): the external parentheses are optional.
f=(f): the parentheses are optional.
Expressions with function-like operators
Rules for operators as ALL, ANY, ROW, SOME, etc.
L(A) = L((A)): the parentheses is optional in the argument.
(L(A)): SYNTAX ERROR.
...More rules? Please help editing here.
ANY is a function-like construct. Like (almost) any other function in Postgres it requires parentheses around its parameters. Makes the syntax consistent and helps the parser avoid ambiguities.
You can think of ANY() like a shorthand for unnest() condensed to a single expression.
One might argue an additional set of parentheses around the set-variant of ANY. But that would be ambiguous, since a list of values in parentheses is interpreted as a single ROW type.

SQLite floating point condition

I am executing the following SQLite query on floating point numbers:
SELECT * FROM Point where x1 < 12 AND x2 > 12
The query works for the less than condition but does not evaluate the greater than condition properly. It seems to think that a value of 6.12 is greater than 12.
Are there any known issues with evaluating floating point numbers in SQLite?
Probably, your x2 column is TEXT data. You must CAST it to float in order to make algebraic comparisons:
SELECT * FROM Point where x1 < 12 AND CAST(x2 AS FLOAT) > 12;
Better, would be converting all your string data to floating point:
UPDATE Point SET x2=CAST(x2 AS FLOAT) WHERE CAST(x2 AS FLOAT)=x2;
This will convert all TEXT floating point numbers to FLOAT.
Probably you are mixing the conditions, your are on a machine that uses the , as decimal separator or you are comparing strings (as suggested by D Stanley in the comments)
My demo in SQLFiddle works as expected.

Why is the output different in SQL Server and same in Oracle?

Why is the output of below two queries is different in SQL Server and same in Oracle ?
SELECT 20.0/-2.0/5
SELECT 20/(-2.0)/5
I'm not agree with your statement that the output should be the same.
If you ask me what 20/-2/5 much output, I will answer you that it could output -2 or -50, depends on implementation details.
In Oracle, the only thing you know is that operators '*' and '/' are evaluated before '+' and '-'. But that's all. I don't find any documentation on the priority gives to operator '*' and '/' between themselves.
Since the two query gives -2, you can assume that the parenthesis are left over, and the calculation is made from left to right.
In SQL Server, the docs specified that
When two operators in an expression have the same operator precedence
level, they are evaluated left to right based on their position in the
expression.
So this computation is conform to the specs :
20/2/5 = (20/2)/5 = 2
Now add the minus sign
20/-2/5 = 20/(-2/5) = -50
Add parenthesis again
20/(-2)/5 = (20/-2)/5 = -2
So not only the parenthesis change the order, but the minus sign too.
In fact, the result should be considered as Undefined, and you can't rely on it.
Add some parenthesis for having a well defined result and prevent headache.