AND OR order of operations - operator-precedence

What is the equivalent of this statement?
if(cond1 AND cond2 AND cond3 OR cond4 AND cond5 AND cond6)
Is it
if((cond1 AND cond2 AND cond3) OR (cond4 AND cond5 AND cond6))
Or
if(cond1 AND cond2 AND (cond3 OR cond4) AND cond5 AND cond6)
Or
if(((cond1 AND cond2 AND cond3) OR cond4) AND cond5 AND cond6)
ect...
This has been something that I've always been scared approaching, to which I just surround the conditions in parenthesis ( ). It would be great if my mind could be settled.

A good way to remember this is to think of it mathematically.
AND as * (multiply)
OR as + (addition)
TRUE as 1
FALSE as 0
So thinking of it as simple math you get this:
0 * 0 = 0
1 * 0 = 0
1 * 1 = 1
0 + 0 = 0
1 + 0 = 1
1 + 1 = 1
Only thing that may be a tiny bit confusing is 1 + 1 = 1, but a bit can't go above 1. But it makes sense if you think of 1 as any non-zero number.
So with this in mind you can then apply this logic:
if(cond1 AND cond2 AND cond3 OR cond4 AND cond5 AND cond6)
Becomes:
if(cond1 * cond2 * cond3 + cond4 * cond5 * cond6)
See: https://en.wikipedia.org/wiki/Order_of_operations

In most languages AND is evaluated first,
hence
if((cond1 AND cond2 AND cond3) OR (cond4 AND cond5 AND cond 6))
is the right choice.
For C#, See http://msdn.microsoft.com/en-us/library/aa691323%28v=vs.71%29.aspx
For C, See http://en.cppreference.com/w/cpp/language/operator_precedence
For Java , See http://bmanolov.free.fr/javaoperators.php

In the normal set of boolean connectives (from a logic standpoint), and is higher-precedence than or, so A or B and C is really A or (B and C). Wikipedia lists them in-order. Most programming languages should obey this convention unless they are really weird.
That said, for your particular language or environment it should be possible to concoct a very small test to satisfy yourself that it is one way or the other :)

Most languages evaluate AND first.

It depends entirely on the language or environment you're asking about, which unfortunately you haven't specified.
AND may have higher precedence over OR, or it may be the other way around, or it may be equal.
It may be evaluated left-to-right, right-to-left or, from the middle outwards in alternating directions if your language is designed by a sadist :-)
It's quite common for AND to have a higher precedence than OR and for them both to be left-to-right associative.
In that case
cond1 AND cond2 AND cond3 OR cond4 AND cond5 AND cond 6
would be equivalent to:
((cond1 AND cond2) AND cond3) OR ((cond4 AND cond5) AND cond 6)

Related

SQL query - find values that meet m conditions out of n

Is there any way to find values that meet any m conditions out of given n conditions? For instance, if there are 10 conditions, and I want to find values that meet any 2 of them.
Use CASE expressions in the WHERE clause, 1 for each condition like this:
WHERE 2 =
CASE WHEN <condition1> THEN 1 ELSE 0 END +
CASE WHEN <condition2> THEN 1 ELSE 0 END +
CASE WHEN <condition3> THEN 1 ELSE 0 END +
..........................................
You can change the = sign to > or < to meet your requirement.
There is. It's not gonna be pretty though.
Start with your conditions as SELECT expressions.
select T.*,
case
when T.SOME_NUMERIC_COLUMN > 0 then 1
else 0
end IS_POSITIVE,
(select sign(COUNT(*))
from SOME_OTHER_TABLE
where parent_id = T.ID) HAS_CHILDREN
...
from SOME_TABLE T
Design these expression in such a way that you get 1 when a condition is met and 0 when it's not.
Then sum up the score and add a WHERE clause.
SELECT *
FROM (
SELECT R.*,
IS_POSITIVE + HAS_CHILDREN + ... SCORE
FROM (...) R)
WHERE SCORE > 2
Of course you're gonna pay a hefty price in performance for this. You won't be able to use your conditions directly to limit the resultset so I'd expect the execution plans to be extremely disappointing. That said, it's not like what you have in mind is a standard task for RDBMS so it should be enough for a proof of concept.

How to implement AND/OR statement logic?

I have a doubt regarding how to implement this statement with constraints:
Only if A or B or both, then C or D or both.
I want to implement it with constraints that take binary values.
This is an example:
If A then B, means that A=B;
A or B or both, means that A+B>=1.
Thank you so much.
Let me try.
First A => B is not the same as A=B. It is however the same as B >= A. If we want: A <=> B then indeed A=B.
The real question seems to be: A+B>=1 <=> C+D>=1 or
A+B>=1 => C+D>=1
A+B=0 => C+D=0
We can write this as a system of inequalities:
C+D >= A
C+D >= B
C+D <= 2(A+B)
All variables are assumed to be binary.

What difference it makes if I use OR statements instead of IN in SQL

What difference it makes if I use, winner IN ('Subject1','Subject2'); & winner='Subject1' OR winner='Subject2';
Queries for the table 17 in the below link:
https://www.w3resource.com/sql-exercises/sql-retrieve-from-table.php#SQLEDITOR
For lists with two elements it doesn't make a difference.
However, MySQL optimizes IN when the list consists of constant expressions. It basically sorts them and does a binary search through the list. This can be a considerable savings with longer lists. As the documentation explains:
If all values are constants, they are evaluated according to the type
of expr and sorted. The search for the item then is done using a
binary search. This means IN is very quick if the IN value list
consists entirely of constants.
In general, IN is safer and does a better job of capturing the column you want. It is very easy to take conditions like this:
where winner = 'Subject1' OR winner = 'Subject2'
and add another condition:
where winner = 'Subject1' or winner = 'Subject2' and
foo = 'bar'
and this logic is probably not longer what you really want -- because it really means:
where winner = 'Subject1' or
(winner = 'Subject2' and foo = 'bar')
This doesn't happen with IN:
where winner in ('Subject1', 'Subject2') and
foo = 'bar'
If there's an index on the column in question, IN vastly out-performs OR. Experience has shown me that the db consistently doesn't use the index when there's an OR on the column.
If there's no index on the column in question, IN out-performs OR if the list is longer than about 5 (it's faster to do a few serial comparisons than traverse a small BTree of values, which is what the DB turns the list into for execution).
IN is also preferred for readability and avoiding SQL's operator precedence trap if brackets are omitted, ie x = a or x = b and c = d is parsed as x = a or (x = b and c = d) instead of the (perhaps) expected (x = a or x = b) and c = d.
Careful when using NOT:
select col1 from
(
select 1 as col1
union all
select 2 as col1
union all
select 3 as col1
union all
select 4 as col1
)x
where x.col1 NOT IN (2,3,4) ;
----------
col1
1
However
select col1 from
(
select 1 as col1
union all
select 2 as col1
union all
select 3 as col1
union all
select 4 as col1
)x
where x.col1 != 2 OR x.col1 != 3 OR x.col1 != 4 ;
---
col1
1
2
3
4

Use previous value in MySQL to compute the next field?

How to use previous values in MySQL to compute the next value? I couldn't explain what I mean more clearly in my poor English (anyone can understand what I asked by seeing the title of this post?), so let me explain it in a snippet:
select
year_id,
sum(case when event_cd >= 20 then 1 else 0 end) as h,
sum(case when ab_fl = "T" then 1 else 0 end) as ab,
h/ab as ba
from events
group by year_id
in the above snippet, when you run the query you will get the error, since there are no such columns in events table as h or ab. However, I want to use h and ab which are computed in the previous sum(case when ~) syntax. I remember there are some sort of ways to make it possible, but I don't remember how to do nor as I said, I couldn't find any relevant posts to meet what I'm asking due to my poor English, though since I'm sure this question is already posted here at SO, it's quite helpful even if you just link it with no detailed explanation.
Thanks.
[Update]
Thanks for the answers. I just wanted to use previous values in order to avoid subqueries and hence lots of redundant typing, and make the entire code more readable. I've used either methods (subqueries or write the entire syntax twice just to compute another value) as described by Mosty Mostacho, and if this is not feasible or pretty risky to use in MySQL, I can surely accept those two methods above. Sorry for the confusion.
There are 2 ways in MySQL (BTW, I've simplified the query a bit but it is still legal):
Option #1: Expand the variables
SELECT
year_id,
SUM(event_cd >= 20) h,
SUM(ab_fl = "T") ab,
SUM(event_cd >= 20) / SUM(ab_fl = "T") ba
FROM events
GROUP BY year_id
Option #2: Use a derived table
SELECT year_id, h, ab, h / ab ba FROM (
SELECT
year_id,
SUM(event_cd >= 20) h,
SUM(ab_fl = "T") ab
FROM events
GROUP BY year_id
) s
You might be tempted to think that the second will run faster but it is not the case. The first one is most likely to run faster because it doesn't need a derived table and can solve the issue in just one pass.
try
select * h/ab as ba from
(
select
year_id,
sum(case when event_cd >= 20 then 1 else 0 end) as h,
sum(case when ab_fl = "T" then 1 else 0 end) as ab,
from events
group by year_id)
source
Update
As #MostyMostacho explains in the comment below, this is not an advisable technique, due to the order of evaluation of user variable being undefined.
You can write a query using a MySQL variable using the syntax #varname := 'value' to store your sums in, and then reference that.
SELECT
year_id
, #h := SUM(CASE WHEN event_cd >= 20 THEN 1 ELSE 0 END) AS h
, #ab := SUM(CASE WHEN ab_fl = "T" THEN 1 ELSE 0 END) AS ab
, #h/#ab AS ba
FROM events
GROUP BY year_id

How to define a custom ORDER BY order in mySQL

In MySQL how do I define a custom sorting order.
To try to explain what I want consider this table:
ID Language Text
0 ENU a
0 JPN b
0 DAN c
1 ENU d
1 JPN e
1 DAN f
2 etc...
here I want to return all rows sorted by Language and ascending ID so that Language = ENU comes first, then JPN and lastly DAN.
The result should be: a,d,b,e,c,f etc.
Is this even possible?
MySQL has a handy function called FIELD() which is excellent for tasks like this.
ORDER BY FIELD(Language,'ENU','JPN','DAN'), ID
Note however, that
It makes your SQL less portable, as other DBMSs might not have such function
When your list of languages (or other values to sort by) gets much longer, it's better to have a separate table with sortorder column for them, and join it to your queries for ordering.
If those are the only three values, then you can use a CASE expression:
ORDER BY `ID`,
CASE `Language`
WHEN 'ENU' THEN 1
WHEN 'JPN' THEN 2
WHEN 'DAN' THEN 3
END
(If there could be other values, then you may want to add some extra logic to keep the ordering consistent; for example, you might add ELSE 4 to that CASE expression, and then order by Language itself as the third ordering criterion:
ORDER BY `ID`,
CASE `Language`
WHEN 'ENU' THEN 1
WHEN 'JPN' THEN 2
WHEN 'DAN' THEN 3
ELSE 4
END,
`Language`
)
You have a couple of options offhand, the first is to change Language to be ENUM (assuming this is possible, and you only expect a few variations)
If you specify it as ENUM('ENU','JPN','DAN') then ORDER Language ASC will order in the order you specify.
The second will involve a case somewhere, i.e.
SELECT * FROM table
ORDER BY CASE Language
WHEN 'ENU' THEN 3
WHEN 'JPN' THEN 2
WHEN 'DAN' THEN 1
ELSE 0
END DESC, ID ASC
Performance-wise the ENUM method will return faster results, but be more hassle if you need to add more languages. A third option would be to add a normalisation table for the Languages however that may be overkill in this instance.
For Yii2 framework we can achieve by following way
Project::find()
->orderBy([
new Expression('FIELD(pid_is_t_m,2,0,1)'),
'task_last_work'=> SORT_ASC
])->all();