Boolean logic OR rearrangement - boolean-logic

Say we have the expression: (¬P v ¬Q) v (P v Q)
Am I allowed to rearrange the expression into: (¬P v P) v (¬Q v Q)?
If so, why is this allowed? Because there are all OR's in the expression?

The "OR" logical operator has two important characteristics here: it's associative (meaning a V (b V c) = (a V b) V c) and commutative (meaning a V b = b V a).
The first property allows you to ignore the parenthesis in a series of "OR"s, and the second lets you rearrange their order however you see fit.

Related

Odd parentheses behavior in Where clause

SETUP:
MySQL 5.7.14 (Google SQL)
DESCRIPTION:
In the following scenario it appears I am getting some false matches in my where clause where I'm NOT using parentheses. But adding the parentheses DOES yield the correct results.
This Query DOES return results with tsd.StatusID = 3 (wrong):
SELECT
tsee.ID, tsd.StatusID
FROM TSShiftDetails tsd
JOIN TSShiftEmployees tse
ON tse.ShiftID = tsd.ID
JOIN TSShiftEmpEntries tsee
ON tsee.ShiftEmpID = tse.ID
WHERE tsee.CCID IN (4590) OR tsee.CCID LIKE null
AND tsd.StatusID != 3
While this query DOES NOT return results with AND tsd.StatusID = 3 (correct):
SELECT
tsee.ID, tsd.StatusID
FROM TSShiftDetails tsd
JOIN TSShiftEmployees tse
ON tse.ShiftID = tsd.ID
JOIN TSShiftEmpEntries tsee
ON tsee.ShiftEmpID = tse.ID
WHERE (tsee.CCID IN (4590) OR tsee.CCID LIKE null)
AND tsd.StatusID != 3
QUESTION:
While I feel I completely understand why the query WITH the parentheses is working. My question is WHY is the one without parentheses returning records with a StatusID == 3? I would think without any functional ordering of parentheses, the AND tsd.StatusID != 3 clause would be applied to every match regardless of the preceding OR.
What Ya'll think? Am I misunderstanding, or is MySQL behaving inconsistently here?
P.S.
FYI, Yes there is a front end application reason for the need to have the Where clause formatted this way. eg. tsee.CCID IN (4590) as opposed to tsee.CCID =4590
The explanation has nothing to do with LIKE NULL or IN ( ).
Boolean expressions follow an order of operator precedence, just like arithmetic.
In arithmetic, you may remember that multiplication has higher precedence than addition:
A + B * C
Without parentheses, this works exactly like:
A + (B * C)
If you want the addition to be evaluated first, you must use parentheses to override the default operator precedence:
(A + B) * C
Similarly, in boolean expressions, AND has higher precedence than OR.
A OR B AND C
Works like:
A OR (B AND C)
If you want the OR to be evaluated first, you must use parentheses to override the default operator precedence:
(A OR B) AND C
How does this explain what you're seeing?
WHERE tsee.CCID IN (4590) OR tsee.CCID LIKE null
AND tsd.StatusID != 3
This works as if you had done:
WHERE tsee.CCID IN (4590) OR (tsee.CCID LIKE null
AND tsd.StatusID != 3)
So if it finds a row with CCID 4590, that row satisfies the whole WHERE clause, because true OR (anything) is still true.

Is there a way with nearest neighbour search in MySQL?

I have the following table:
CREATE TABLE numbert_t ( v DOUBLE , id INTEGER, INDEX(v) )
and I want to do a query with a paremeter q that sorts the points in distance abs( q - v ). For example
SELECT v, id, ABS( q - v ) AS d FROM number_t ORDER BY d
I tried the query above and this one:
SELECT v, id, (v - q) AS d FROM numbers_t WHERE (v - q) > 0
ORDER BY d
I also tried slight variations of the above:
SELECT v, id, (v - q) AS d FROM numbers_t WHERE v > q ORDER BY v
They are not equivalent, but I don't mind to do two queries and have two independent cursors. However, in all cases EXPLAIN says that filesort, no indices would be used. Can I get MySQL to somehow use indices for this problem?
Did you try:
SELECT MIN(v), id FROM number_t WHERE v >= q
UNION
SELECT MAX(v), id FROM number_t WHERE v < q
MySQL specific, not standard, because of the id. But the id might be retrieved after you have gotten exact values.
You can use the spatial extension and a point datatype. Then you can use a proximity search for example when a point is inside a bounding box. You can also use my quadkey library. It uses a hilbert curve and a mercator projection. You can download my php class hilbert curve # phpclasses.org.

Alternatives to Multiple Case Statements for Same Column

To match up some new schema to old, I'm having to do some ugly contortions that I figure could be done in a better way. For reference, I asked another question about this match-up process here: Creating View from Related Child Tables
I've placed a simplified example in SQLFiddle but the gist of it is, that the only way I can see reconciling these two different schemas is to do two case statements on the same value, something like this:
SELECT
CASE
WHEN n.FooBarStatusId = 1 OR n.FooBarStatusId = 2
THEN 1
ELSE 0
END as [IsFoo],
CASE
WHEN n.FooBarStatusId = 2
THEN 1
ELSE 0
END as [IsBar]
from Parent p
left join OldStuff o on p.ParentId = o.ParentId
left join NewStuff n on p.ParentId = n.ParentId
Is there a better and/or more efficient way of accomplishing the same thing? These case statements could be hit hundreds of times in a given query and I'm concerned about this specific logic.
I've thought about extracting this specific logic out (it is part of a larger query to build a view) into a temp table or perhaps even a table-valued function, but even still I can't come up with a way around using multiple case statements.
Just corrected grammar...
I found another solution:
select
p.Name,
ISNULL(o.IsFoo, CONVERT(BIT, n.FooBarStatusId)) as [IsFoo],
ISNULL(o.IsBar, CONVERT(BIT, n.FooBarStatusId * (n.FooBarStatusId - 1))) as [IsBar],
from Parent p
left join OldStuff o on p.ParentId = o.ParentId
left join NewStuff n on p.ParentId = n.ParentId
The only one arithmetic solution could be slow:
select
p.Name,
ISNULL(o.IsFoo, CAST( (n.FooBarStatusId % 0.35) * 4 AS int)) AS [IsFoo],
ISNULL(o.IsBar, n.FooBarStatusId/2) [IsBar]
from Parent p
left join OldStuff o on p.ParentId = o.ParentId
left join NewStuff n on p.ParentId = n.ParentId
Personally, I do not like to use the division, because of could be involved floating point operations, that way, it would be very slow.
As you have two columns, you will need two expressions... but they might not have to be CASE expressions. Reading your question, I get the impressions that the only possible values in the column are 0,1,2, and that this is an int type? If that's correct, you can use arithmetic rather than boolean logic to get what you need. Try this:
CAST( (n.FooBarStatusId % .35) * 4 AS int) AS [IsFoo],
n.FooBarStatusId/2 [IsBar]

MySQL Stored Procedure Design Problem V2. Recusion or Hierarchy?

Suppose we have a table named Connected, with column node_1 and node_2, both integer type, and some data in it.
It looks like this:
`node_1` `node_2`
A B
C D
B C
B F
C W
D N
D Q
.
.
. Much much much more
.
What Im trying to do is expand this table, and then collect all relations. For instance, if we can travel from 'A' to 'Q' with path 'A-B-C-D-Q' ( defined by the old table, 'A-B, B-C, C-D, D-Q'), we say that 'A' and 'Q' can be connected, and insert this pair into new table.
Such that, the result table should looks like this:
`node_1` `node_2`
A B
A C
A D
A F
A N
A Q
A W
B C
B D
B F
B N
B Q
B W
C D
C N
C Q
C W
D Q
D N
I appreciate all helps !
Change the word "Node" to "Group",
"connected" to "contains", does it
sound more reasonable? Im Sorry for my
gramma or any other language related
problemssss :)
Same as my other solution, just use ASCII() around the character to the its ascii value in the SELECT.
MySQL Stored Procedure Design Problem. Recusion or Hierarchy?
PS. due to our conversation in the other question. Im getting the impression your really content of finding a imperative solution for this. Remember, SQL is a declarative language.

MySQL issue: LEFT JOIN on empty table

Given a database with two tables X and Y, I have a query that should LEFT JOIN the two tables on attributes X.a1 and Y.b1. I used the following query:
SELECT X.a1, X.a2, Y.b1, Y.b2 FROM X LEFT JOIN Y ON (X.a1 = Y.b1)
I thought that would be good enough to work, even if Y is currently an empty table. However, the query breaks because table Y is empty, it seems. Is there any way to reformat this query so that even if Y is an empty table, the LEFT JOIN will not break? Or do I just need to always make sure that there is some data in table Y, even if it doesn't match anything in table X (hence the LEFT JOIN).
Since you didn't post your actual SQL, i just make assumption here. My experience telling me that you might have a where clause that causes the SQL to return empty set.
SELECT X.a1, X.a2, Y.b1, Y.b2 FROM X LEFT JOIN Y ON (X.a1 = Y.b1)
WHERE Y.b3 = 'something'
The above SQL will return empty result set. You may need to modify your SQL into the following format, by bring up the problematic where clause to LEFT JOIN ON clause.
SELECT X.a1, X.a2, Y.b1, Y.b2 FROM X
LEFT JOIN Y ON (X.a1 = Y.b1 and Y.b3 = 'something')
Your table names are a little confusing. Is it X and Y, or X.a and Y.b?
If X and Y:
SELECT X.a1, X.a2, Y.a1, Y.b2 FROM X LEFT OUTER JOIN Y ON (X.a1 = Y.b1)
should bring back all X, with nulls for the Y.a1 and Y.b2 where there is no matching record.
Try your query on some Sql editor that returns errors like
HeidiSQL or similar. In my case the problem was ambiguous id in WHERE clause.