Where clause operator precedence - sql

Can anyone tell me the precedence of the following where clausule (using parentheses), Mariadb? I can't figure it out because of the multiple and's
WHERE
(
A = 1
)
OR
(
B = 2
)
AND
(
C = 3
)
AND
(
D = 4
)
Thanks in advance!

AND goes before OR.
What you get is WHERE A = 1 or (b = 2 and c = 3 and D = 4).
Is that what you want?

Related

Error in SQL Server of join two tables with case (when...end):

Update: I get an error when join two tables with case (when..end):
tmp1:
A B C
---------------
1 1 1
NULL 1 2
NULL 2 1
2 2 2
tmp2:
A B C D
---------------
1 1 1 X
2 1 1 Y
1 1 2 Z
2 1 2 X
1 2 1 Y
2 2 1 Z
1 2 2 X
2 2 2 Z
I want to join two tables and get tmp1.* + tmp2.D. If tmp1.A is not null, use TMP1.A = TMP2.A, TMP1.B = TMP2.B, AND TMP1.C = TMP2.C to join.
If tmp1.A is null, set tmp1.A = [MIN(TMP2.A) OVER (PARTITION BY TMP2.B, TMP2.C)] and then join. Here is the results what I want:
A B C D
-------------------
1 1 1 X
1 1 2 Z
1 2 1 Y
2 2 2 Y
The following is my codes, I got the error
An expression of non-boolean type specified in a context where a condition is expected, near 'END'
Actually I am not sure how to join them correctly? Any suggestion will be appreciate!
SELECT TMP1.*, TMP2.D
FROM TMP1
LEFT JOIN TMP2 ON CASE
WHEN TMP1.A IS NOT NULL
THEN 'TMP1.A = TMP2.A AND TMP1.B = TMP2.B AND TMP1.C = TMP2.C'
WHEN TMP1.A IS NULL
THEN 'TMP1.A = MIN(TMP2.A) OVER (PARTITION BY TMP2.B, TMP2.C)
AND TMP1.B = TMP2.B
AND TMP1.C = TMP2.C'
END
I don't know if the single quotes are typos or not. If they are intentional, then they are just strings and have nothing to do with the logic being processed (and will generate a syntax error without a comparison of some sort after the case expression)
Assuming the strings represent the logic you do want, you can express the logic without a case expression, using just boolean logic:
SELECT TMP1.*, TMP2.D
FROM TMP1 LEFT JOIN
TMP2
ON (TMP1.A IS NOT NULL AND TMP1.A = TMP2.A AND TMP1.B = TMP2.B AND
TMP1.C = TMP2.C
) OR
(TMP1.A IS NULL AND TMP1.A = MIN(TMP2.A) OVER (PARTITION BY TMP2.B, TMP2.C) AND
TMP1.B = TMP2.B AND TMP1.C = TMP2.C
)
I will don't think this will work, because the window function is not allowed in an ON clause. Perhaps this expresses what you intend:
SELECT TMP1.*, TMP2.D
FROM TMP1 LEFT JOIN
(SELECT TMP2.*,
MIN(TMP2.A) OVER (PARTITION BY TMP2.B, TMP2.C) as MIN_A
FROM TMP2
) TMP2
ON (TMP1.A IS NOT NULL AND TMP1.A = TMP2.A AND TMP1.B = TMP2.B AND
TMP1.C = TMP2.C
) OR
(TMP1.A IS NULL AND TMP1.A = TMP2.MIN_A AND
TMP1.B = TMP2.B AND TMP1.C = TMP2.C
)
Of course, the second part of the boolean expression will always be treated as FALSE (technically it evaluates as NULL) because TMP1.A is NULL and yet you are trying to compare it to something else.
These are very arcane conditions. I wonder if they are really needed. Alternative ways to implement the logic are appropriate for another question, with a better explanation of what you are doing, along with sample data and desired results.
Try this query. I found min(a) for each b and c combinations using correlated subquery, then joined with tmp2 to get final result
select
t.a, t.b, t.c, q.d
from (
select
a = isnull(a.a, (select min(b.a) from tmp2 b where a.b = b.b and a.c = b.c))
, a.b, a.c
from
tmp1 a
) t join tmp2 q on t.a = q.a and t.b = q.b and t.c = q.c

sql function case returns more than one row

Going to use this query as a subquery, the problem is it returns many rows of duplicates. Tried to use COUNT() instead of exists, but it still returns a multiple answer.
Every table can only contain one record of superRef.
The below query I`ll use in SELECT col_a, [the CASE] From MyTable
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = myTable.sysno AND A_specAttr = 'value')
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo WHERE C_superRef = myTable.sysno AND b_type = 2)
THEN 2
ELSE (SELECT C_intType FROM C
WHERE C_superRef = myTable.sysno)
END
FROM A, B, C
result:
3
3
3
3
3
3...
What if you did this? Because Im guessing you are getting an implicit full outer join A X B X C then running the case statement for each row in that result set.
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM ( SELECT COUNT(*) FROM A ) --This is a hack but should work in ANSI sql.
--Your milage my vary with different RDBMS flavors.
DUAL is what I needed, thanks to Thorsten Kettner
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM DUAL

Order of operations for SQL?

Suppose I have this statement:
SELECT * FROM MyTable WHERE a = 1 or b = 2 and c = 3
Does that mean: (a = 1) OR (b = 2 AND c = 3) or does it mean (a = 1 or b = 2) AND c = 3? Can I change what it means, i.e. execute the OR before the AND or is this not possible?
From Technet:
When more than one logical operator is used in a statement, AND
operators are evaluated first. You can change the order of evaluation
by using parentheses.
So yes, it means (a = 1) OR (b = 2 AND c = 3).
You can force the behavior you want by writing the parentheses as you did above: (a = 1 OR b = 2) AND c = 3

Searching Multiple Rows at a time through a single SQL query

I have a table whose data is in this manner.
A B C
---------
0 6 2
0 3 4
1 0 2
1 1 4
I wrote a SQL query -
select A
from Table
where (B = 6 and C = 2) AND (B = 3 and C = 4).
Obviously it returned zero results since this query would search in the same row. Please help me with writing a better one to produce results such that it can check two rows with a single statement.
EDIT:
I am not looking for 'OR' statement. I need to find an element of A such that it has two corresponding rows AND each of the rows has elements 6,2 and 3,4 present in columns B,C correspondingly.
PS.
(I don't have the option of writing two queries and then finding the common elements of two set.)
Many thanks in advance
I guess you want something like this
select A
from YourTable
where (B = 6 and C = 2) or
(B = 3 and C = 4)
group by A
having count(distinct B) >= 2
Try here:
https://data.stackexchange.com/stackoverflow/q/123711/
Use OR instead of AND
select A from Table where (B=6 and C=2) OR (B=3 and C=4).
If you want the onlu result use DISTINCT
select DISTINCT A from Table where (B=6 and C=2) OR (B=3 and C=4).
If you need to check the equality of A, use this:
select t1.A
from Table t1
JOIN Table t2 ON t1.A = t2.A
where T1.B=6 and t1.C=2 AND t2.B=3 and t2.C=4
As you see - using AND again
Are you trying to get this??
SELECT A
FROM Table
WHERE (B = 6 AND C = 2) OR (B = 3 AND C = 4)
This would return the A column for all four rows again.
If not: WHAT exactly are you trying to select?
IF you want just two rows, one with A = 0, one with A = 1, then use DISTINCT:
SELECT DISTINCT A
FROM Table
WHERE (B = 6 AND C = 2) OR (B = 3 AND C = 4)
Maybe:
select A
from Table
where (B = 6 and C = 2)
INTERSECT
select A
from Table
(B = 3 and C = 4)

SQL Server Where Clause Case Statement?

I have a Where Clause that checks the existence of rows in a subquery, but I only want to execute that check if a bit is set to 1. So for example:
Select * from Listing l
Where
l.IsDeleted=1
AND CASE WHEN #MustHasPicture = 1 THEN
(
EXISTS
(
SELECT NULL AS [EMPTY]
FROM [dbo].[ListingPictures] AS [lp]
INNER JOIN Listing l ON lp.ListingID=l.ID
)
)
ELSE 1 END = 1
This syntax is wrong, and I'm hoping someone can point me in the right direction. Thanks.
SELECT *
FROM Listing l
WHERE IsDeleted = 1
AND ( #MustHasPicture <> 1 OR
(#MustHasPicture = 1 AND l.id IN (
SELECT listingid
FROM ListingPictures
)
)
)
No need to do a case - if the first part of an and fails, the second part will not be performed.
select
*
from
Listing l
Where
l.IsDeleted = 1
and ((#MustHasPicture = 1 and exists (...)) or 1)
What about this one:
SELECT * FROM Listing l
WHERE l.IsDeleted = 1
AND (#MustHasPicture = 1
AND EXISTS(SELECT * FROM [dbo].[ListingPictures] AS [lp]
WHERE lp.ListingID = l.ID)
OR #MustHasPicture = 0)
But where does the Value #MustHasPicture come from?