I am refactoring some old oracle sql statements containing plenty of conditions. Some are single conditions put into brackets. Now, does the brackets matter for single conditions? Is there a difference between the two examples below?
example 1
WHERE
(
A = B
AND B = C
)
AND ( A > 5 )
AND ( B <> 0 )
example 2
WHERE
(
A = B
AND B = C
)
AND A > 5
AND B <> 0
As far as I know there ain't any semantic differences.
In my experience usually this is either
a relic of some old condition (maybe an OR was in that bracket somewhere in the past) or
just the style of the dev working in this.
There is no difference between the two examples you have posted. Oracle query executes from the end i.e your where condition's last part is filtered first and runs back eg:- where first filter condition would be b<>0 then A>5 ,so on.
Its good practice to use brackets when using AND and OR operators together as without brackets soemtimes the logic is unclear ,otherwise with only AND operator bracket doesn't make any difference
What about logic: you do need brackets if you have some OR logic, but in this case (only AND) it has no meaning. You can remove all brackets in your query.
And if we'll go deep: look the explain query analyze, you can see that interpreter puts brackets automatically even you missed it.
All are same until you have only AND. But if you have any other operator then comes the question of precedence.
example 1
WHERE
(
A = B
AND B = C
)
AND ( A > 5 )
AND ( B <> 0 )
example 2
WHERE
(
A = B
AND B = C
)
AND A > 5
AND B <> 0
example 3
WHERE
A = B
AND B = C
AND A > 5
AND B <> 0
Related
I need to return elements from a database query based on an inequality using the lexicographic ordering on multiple columns. As described in this question this is straightforward if I'm comparing all the columns in the same direction. Is there a straigtforward way to do this if I want to reverse the direction of the sort on some columns.
For instance, I might have columns A, B and C and values 5, 7, and 23 and I'd like to return something like:
WHERE A < 5 OR (A = 5 AND B > 7) OR (A = 5 AND B = 7 AND C < 23)
Is there any easier way to do this using tuples (I have to construct in a function without knowing the number of columns beforehand)? Note that, some columns are DateTime columns so I can't rely on tricks that apply only to integers (e.g. negating both sides). I'm happy to use postgresql specific tricks.
And, if not, is there a specific way/order I should build expressions like the above to best use multicolumn indexes?
Just thinking if going the CTE route and creating a column which stores 0 or 1 for whether the data passes the specific filter criteria or not.
WITH CTE AS
(
SELECT
..,
...,
CASE
WHEN A < 5 THEN 1
WHEN A = 5 AND B > 7 THEN 1
WHEN A = 5 AND B = 7 AND C < 23 THEN 1
ELSE 0
END AS filter_criteria
)
SELECT
..,
..
FROM
CTE
WHERE filter_criteria = 1
OR, directly applying the CASE statement in the WHERE clause. This reduces the extra step of CTE
WHERE 1 = CASE
WHEN A < 5 THEN 1
WHEN A = 5 AND B > 7 THEN 1
WHEN A = 5 AND B = 7 AND C < 23 THEN 1
ELSE 0
END
Referring to the thread you mentioned, can you try the idea WHERE (col_a, 'value_b') > ('value_a', col_b)
I've come across following T-SQL today:
select c from (select 1 union all select 1) as d(c)
that yields following result:
c
-----------
1
1
The part that got me confused was d(c)
While trying to understand what's going on I've modified T-SQL into:
select c, b from (select 1, 2 union all select 3, 4) m(c, b)
which yields following result:
c b
----------- -----------
1 2
3 4
It was clear that d & m are table reference while letters in brackets c & b are reference to columns.
I wasn't able to find relevant documentation on msdn, but curious if
You're aware of such syntax?
What would be useful use case scenario?
select c from (select 1 union all select 1) as d(c)
is the same as
select c from (select 1 as c union all select 1) as d
In the first query you did not name the column(s) in your subquery, but named them outside the subquery,
In the second query you name the column(s) inside the subquery
If you try it like this (without naming the column(s) in the subquery)
select c from (select 1 union all select 1) as d
You will get following error
No column name was specified for column 1 of 'd'
This is also in the Documentation
As for the usage, some like to write it the first method, some in the second, whatever you prefer. It's all the same
An observation: Using the table constructor values gives you no way of naming the columns, which makes it neccessary to use column naming after the table alias:
select * from
(values
(1,2) -- can't give a column name here
,(3,4)
) as tableName(column1,column2) -- gotta do it here
You've already had comments that point you to the documentation of how derived tables work, but not to answer you question regarding useful use cases for this functionality.
Personally I find this functionality to be useful whenever I want to create a set of addressable values that will be used extensively in your statement, or when I want to duplicate rows for whatever reason.
An example of addressable values would be a much more compelx version of the following, in which the calculated values in the v derived table can be used many times over via more sensible names, rather than repeated calculations that will be hard to follow:
select p.ProductName
,p.PackPricePlusVAT - v.PackCost as GrossRevenue
,etc
from dbo.Products as p
cross apply(values(p.UnitsPerPack * p.UnitCost
,p.UnitPrice * p.UnitsPerPack * 1.2
,etc
)
) as v(PackCost
,PackPricePlusVAT
,etc
)
and an example of being able to duplicate rows could be in creating an exception report for use in validating data, which will output one row for every DataError condition that the dbo.Product row satisfies:
select p.ProductName
,e.DataError
from dbo.Products as p
cross apply(values('Missing Units Per Pack'
,case when p.SoldInPacks = 1 and isnull(p.UnitsPerPack,0) < 1 then 1 end
)
,('Unusual Price'
,case when p.Price > (p.UnitsPerPack * p.UnitCost) * 2 then 1 end
)
,(etc)
) as e(DataError
,ErrorFlag
)
where e.ErrorFlag = 1
If you can understand what these two scripts are doing, you should find numerous examples of where being able to generate additional values or additional rows of data would be very helpful.
We're dealing with geographic data with our Oracle database.
There's a function called ST_Insertects(x,y) which returns true if record x intersects y.
What we're trying to do is, compare each record of table A with all records of table B, and check two conditions
condition 1 : A.TIMEZONE = 1 (Timezone field is not unique)
condition 2 : B.TIMEZONE = 1
condition 3 : ST_Intersects(A.SHAPE, B.SHAPE) (Shape field is where the geographical information is stored)
The result we're looking for is records ONLY from the table A that satisfy all 3 conditions above
We tried this in a single select statement but it doesn't seem to make much sense logically
pseudo-code that demonstrates a cross-join:
select A.*
from
tbl1 A, tbl2 B
where
A.TIMEZONE = 1 and
B.TIMEZONE = 1 and
ST_Intersects(A.SHAPE, B.SHAPE)
if you get multiples, you can put a distinct and only select A.XXX columns
With a cross-join rows are matched like this
a.row1 - b.row1
a.row1 - b.row2
a.row1 - b.row3
a.row2 - b.row1
a.row2 - b.row2
a.row2 - b.row3
So if row 1 evaluates to true on multiple rows, then just add a distinct on a.Column1, etc.
If you want to use the return value from your function in an Oracle SQL statement, you will need to change the function to return 0 or 1 (or 'T'/'F' - some data type supported by Oracle Database, which does NOT support the Boolean data type).
Then you probably want something like
select <columns from A>
from A
where A.timezone = 1
and exists ( select *
from B
where B.timezone = 1
and ST_intersects(A.shape, B.shape) = 1
)
Suppose I have this query:
UPDATE TEST SET
a = a + 23,
b = (b+5)/a,
c = c + a + b
WHERE
d = 6
OR
d = 10
and the original values of the columns is
a = 0
b = 5
c = 10
Will the query crash because of the 0 value of a (so (b+5)/a won't calculate) or will a already have value = 23.
The general question is: in an UPDATE statement, the values used to update the further columns are the original values of the already updated columns or the updated values?
Are there difference between the database used? MySQL, SQL Server, Oracle, DB2, ...?
EDIT
What would be the best practise to have the updated values on the "right side"?
Subqueries will work?
How to solve the problem of multiple values updated? Subqueries should return only 1 value
UPDATE TEST SET
a = a + 23,
b = (b+5)/(SELECT a FROM TEST WHERE d = 6),
c = c + a + b
WHERE
d = 6
OR
d = 10
In all SQL databases I know of except MySQL, all updates are done exactly simultaneously, which means a will be zero in the update of b.
In MySQL, the updates are done in order, which means a will be 23.
A very simple PostgreSQL example and a MySQL example with a different result.
In all ANSI compliant database systems, transactions are atomic and isolated, which means they happen all at once. Your query will crash for the given values.
i cant quite figure out how to put this into a simple question, so I'll explain what I have and what I need to do.
Table A
|..ItemNum..|..ItemUse..|..SubC..|..MainC..|
|..123..|..B..|..AAA..|..QQQ..|
|..456..|..J..|..BBB..|..QQQ..|
|..123..|..D..|..DDD..|..RRR..|
|..789..|..C..|..CCC..|..WWW..|
|..345..|..W..|..EEE..|..TTT..|
|..678..|..B..|..FFF..|..YYY..|
I need to make a list of ItemNum and MainC that are grouped into 3 categories:
B / C / D = 1
<anything else> = 2
B / C / D & <anything else> = 3
So my results would be:
|..MainC..|..Group..|
|..QQQ..|..3..|
|..RRR..|..1..|
|..WWW..|..1..|
|..TTT..|..2..|
|..YYY..|..1..|
I've got an iif setup that takes care of groups 1 and 2, but cant figure out how to get the values in MainC to come out with Group 3.
Any ideas?
I don't understand your explanation ( especially the mapping to 3 ) but here's a shot:
select MainC, case when ItemUse in ('B','C','D') then 1
else 2
end as group
from A