Complex SQL condition in Spring Data Jpa Specification [duplicate] - spring

Are the two statements below equivalent?
SELECT [...]
FROM [...]
WHERE some_col in (1,2,3,4,5) AND some_other_expr
and
SELECT [...]
FROM [...]
WHERE some_col in (1,2,3) or some_col in (4,5) AND some_other_expr
Is there some sort of truth table I could use to verify this?

And has precedence over Or, so, even if a <=> a1 Or a2
Where a And b
is not the same as
Where a1 Or a2 And b,
because that would be Executed as
Where a1 Or (a2 And b)
and what you want, to make them the same, is the following (using parentheses to override rules of precedence):
Where (a1 Or a2) And b
Here's an example to illustrate:
Declare #x tinyInt = 1
Declare #y tinyInt = 0
Declare #z tinyInt = 0
Select Case When #x=1 OR #y=1 And #z=1 Then 'T' Else 'F' End -- outputs T
Select Case When (#x=1 OR #y=1) And #z=1 Then 'T' Else 'F' End -- outputs F
For those who like to consult references (in alphabetic order):
Microsoft Transact-SQL operator precedence
Oracle MySQL 9 operator precedence
Oracle 10g condition precedence
PostgreSQL operator Precedence
SQL as understood by SQLite

I'll add 2 points:
"IN" is effectively serial ORs with parentheses around them
AND has precedence over OR in every language I know
So, the 2 expressions are simply not equal.
WHERE some_col in (1,2,3,4,5) AND some_other_expr
--to the optimiser is this
WHERE
(
some_col = 1 OR
some_col = 2 OR
some_col = 3 OR
some_col = 4 OR
some_col = 5
)
AND
some_other_expr
So, when you break the IN clause up, you split the serial ORs up, and changed precedence.

Arithmetic operators
Concatenation operator
Comparison conditions
IS [NOT] NULL, LIKE, [NOT] IN
[NOT] BETWEEN
Not equal to
NOT logical condition
AND logical condition
OR logical condition
You can use parentheses to override rules of precedence.

Query to show a 3-variable boolean expression truth table :
;WITH cteData AS
(SELECT 0 AS A, 0 AS B, 0 AS C
UNION ALL SELECT 0,0,1
UNION ALL SELECT 0,1,0
UNION ALL SELECT 0,1,1
UNION ALL SELECT 1,0,0
UNION ALL SELECT 1,0,1
UNION ALL SELECT 1,1,0
UNION ALL SELECT 1,1,1
)
SELECT cteData.*,
CASE WHEN
(A=1) OR (B=1) AND (C=1)
THEN 'True' ELSE 'False' END AS Result
FROM cteData
Results for (A=1) OR (B=1) AND (C=1) :
A B C Result
0 0 0 False
0 0 1 False
0 1 0 False
0 1 1 True
1 0 0 True
1 0 1 True
1 1 0 True
1 1 1 True
Results for (A=1) OR ( (B=1) AND (C=1) ) are the same.
Results for ( (A=1) OR (B=1) ) AND (C=1) :
A B C Result
0 0 0 False
0 0 1 False
0 1 0 False
0 1 1 True
1 0 0 False
1 0 1 True
1 1 0 False
1 1 1 True

Here's a variant of the '3-variable truth table' using booleans
WITH truth_values AS
(SELECT FALSE AS A,
FALSE AS B,
FALSE AS C
UNION ALL SELECT FALSE,
FALSE,
TRUE
UNION ALL SELECT FALSE,
TRUE,
FALSE
UNION ALL SELECT FALSE,
TRUE,
TRUE
UNION ALL SELECT TRUE,
FALSE,
FALSE
UNION ALL SELECT TRUE,
FALSE,
TRUE
UNION ALL SELECT TRUE,
TRUE,
FALSE
UNION ALL SELECT TRUE,
TRUE,
TRUE),
logics AS
(SELECT truth_values.*,
a
OR b
AND c AS no_parens, (a
OR b)
AND c AS or_parens
FROM truth_values)
SELECT *,
no_parens != or_parens AS parens_made_a_difference
FROM logics
ORDER BY a,
b,
c
With these results:
#
A
B
C
no_parens
or_parens
parens_made_a_difference
1
false
false
false
false
false
false
2
false
false
true
false
false
false
3
false
true
false
false
false
false
4
false
true
true
true
true
false
5
true
false
false
true
false
true
6
true
false
true
true
true
false
7
true
true
false
true
false
true
8
true
true
true
true
true
false
If 'parens_made_a_difference' is true, then the parentheses made a difference.

Related

How to change the element part of an array while iterating

An array xs consists of numbers from 0 to 9:
xs = [*0..9]
Test parity, and store result in place:
xs.map!(&:odd?)
puts xs.join(" ")
# => false, true, ..., true
xs changed as expected. But I just want to change a part of the array
xs[5..-1].map!(&:odd?)
puts xs.join(" ")
# => 0 1 2 3 4 5 6 7 8 9
I guess the slice operation returns a copy. Or some other reasons.
xs[...] = xs[...].some_operation is a solution, but is there any way to do this without assignment?
Here is a way to do this:
xs.fill(5..-1) { |i| xs[i].odd? }
#=> 0 1 2 3 4 true false true false true

Understanding challenge "a^b is considered powerful iff a^b >= 2 * b^2 and a^b >= (a*b)^2"

Can you help I don't understand challenge from https://www.learneroo.com/modules/61/nodes/338#stq=&stp=0
Challenge
ab is considered powerful if (and only if) both of the following 2 conditions are met:
ab >= 2 * b2
ab >= (a*b)2
return true if ab is powerful and false otherwise.
my answer
def do_stuff(a, b)
a*b >= 2*b*2
a*b >= (a*b)*2
end
#boilerplate code
t = gets.to_i
for i in 1..t do
a, b = gets.strip.split.map {|i| i.to_i}
puts do_stuff(a, b)
end
Input Correct Output Your Output
2 4 false false
3 5 true false
10 1 false false
7 15 true false
6 2 false false
4 5 true false
4 3 false false

Oracle CASE short-circuit not working in group by

I've found in the documentation of case statment that it uses short-circuit:
Oracle Database uses short-circuit evaluation. That is, for a simple
CASE expression, the database evaluates each comparison_expr value
only before comparing it to expr, rather than evaluating all
comparison_expr values before comparing any of them with expr.
Consequently, Oracle never evaluates a comparison_expr if a previous
comparison_expr is equal to expr. For a searched CASE expression, the
database evaluates each condition to determine whether it is true, and
never evaluates a condition if the previous condition was true.
But the following SQL is returning divisor is equal to zero:
WITH data AS (SELECT 1 AS cond, 10 AS num, 0 AS div FROM DUAL)
SELECT
CASE WHEN cond = 2 THEN (CASE WHEN MAX(div) = 0 THEN 0 ELSE SUM(num / div) END)
ELSE -1
END AS result
FROM data
GROUP BY cond
Any solution to avoid divisor is equal to zero error?
EDIT
This query works fine:
WITH data AS (SELECT 1 AS cond, 10 AS num, 0 AS div FROM DUAL)
SELECT
CASE WHEN cond = 2 THEN (CASE WHEN MAX(div) = 0 THEN 0 ELSE 1 END)
ELSE -1
END AS result
FROM data
GROUP BY cond
Use
CASE WHEN cond = 2
THEN SUM(case when div = 0 then 0 else num / div end)
ELSE -1
END

Ruby logical "and" operator

When playing with IRB I came across this:
a = -1
b = 1
(a and b) > 0
returns true, however
(false and true) == true
returns false.
Why does the first statement return true? In the 'pickaxe' I read "Both and and && evaluate to true only if both operands are true. They evaluate the second operand only if the first is true[...]"
This implies -- to me -- that the first statement should return false
Why should it be false? Both operands a and b are not false, and even not nil..
IIRC, in Ruby, every value different than false/nil is considered true. Even zero. Hence 0 and 0 is true. -1 and 1 surely too!
EDIT: aah, I just grasped what you meant. You mean that the first expression -1 and 1 should return -1? No, that's what OR does!
-1 and 1 => 1
-1 or 1 => -1
AND evaluates ALL operand for 'true' result, and reduces checks only if one item is 'false'.
OR evaluates ALL operand for 'false' result, and reduces checks only if one item is 'true'
Both -1 and 1 are "truthy" values from ruby's point of view. That's why
-1 and 1 # => 1
false and true => false
that the first statement should return false
I don't see where you got this from. Aren't you confusing it with OR operator?
a = -1
b = 1
a and b # => 1
(a and b) > 0 # => true
a && b # => 1
(a && b) > 0 # => true
a || b # => -1
(a || b) > 0 # => false
in ruby, the only time an object is false is if it is false or nil.
>> !!nil # false
>> !!false # false
>> !!-1 # true
in your syntax, it is impossible to get what you want to say when you try
>> (1 and -1) > 0
since and should be used to return true or false but what I found interesting is the value returned
>> (1 and -1) # -1
>> (-1 and 1) # 1
so having (b and a) > 0 would return false which is interesting
(1 and -1) will return -1 since the and operator needs to satisfy all conditions. there's something wrong with me today.

how to describe this series in code?

i would like to find a formula describing this series.
i need to set a boolean depending on a positive integer.
it's pretty simple but i am stuck and feel a bit stupid.
0 false
1 true
2 true
3 false
4 false
5 true
6 true
7 false
8 false
9 true
10 true
11 false
12 false
...
so the flag changes at every odd number
Well, for the flag changing at every odd number, it looks like your boolean should be true if and only if (n+3)%4 <= 1, where % is the modulo operator:
n (n+3)%4 Boolean
-- ------- -------
0 3 false
1 0 true
2 1 true
3 2 false
4 3 false
5 0 true
6 1 true
7 2 false
8 3 false
9 0 true
10 1 true
11 2 false
12 3 false
:: : : :
I've deliberately added three instead of subtracting one, since some languages have different ideas of what the modulo operator should do for negative numbers. And keep in mind that this is language-agnostic. If you're specifically looking for a C or C-like language solution, see the excellent answer here from Christoffer Hammarström ((n + 1) & 2 just in case it ever disappears) - this is far more succinct in those particular languages.
In C and other languages where non-zero is true: (n + 1) & 2, and in other languages: (n + 1) & 2 != 0.
You can first divide the int value by 2 and then check if it is even or odd.
boolean flag = ((i+1)/2)%2!=0;
Maybe there is an off-by-one error, so check this.
N (N+1)/2 ((N+1)/2)%2 compare != 0
0 0 0 false
1 1 1 true
2 1 1 true
3 2 0 false
4 2 0 false
5 3 1 true
6 3 1 true
7 4 0 false
8 4 0 false
9 5 1 true
...
Flag changes at every odd number, means the last bit is set to 1.
1 => 01, 3 => 11, ... 9 => 1001, 11 => 1011
and so on..
so, u can just check the last bit at each step and whenever it is 1, flip the flag.

Resources