Does oracle /netezza execute subqueries only once - oracle

In this query:
select L1.*, L2.* from (select t1.col1, max(t1.col2) from ($subquery) t1, group by t1.col1) L1, ($subquery) L2 where L1.col1 = L2.col1
Will Oracle/Netezza execute the $subquery only once? Or twice?

Oracle will execute two times. (Actually this isn't 100% accurate. It will execute only the main (compound) query once, but probably it will access the subquery's table's 2 different times/way.)
You should use with for optimizing this way.
(Otherwise you could use MAX() OVER (PARTITION BY ....) for similar things as well.)

Related

how to compare one value against 2 values in Oracle

I want to compare a a value against 2 values without using OR or DECODE. The value I want to compare with two values is the one which I am getting as a return code of a function. If I use OR or DECODE then I have to call function twice and it gives performance hit. Currently I am coding as below
select *
from table1 t1, table2 t1
where t1.empid = t2.empid
and myfunction(t2.balance) = t1.total OR myfunction(t2.balance) = -1
Please suggest if there is a way to call function once and compare with 2 values.
To shorten your code you could use IN operator which acts like OR.
select *
from table1 t1
join table2 t1 on
t1.empid = t2.empid
and myfunction(t2.balance) in (t1.total, -1)
I've also replaced old-fashioned join syntax in where clause for JOIN keyword and you're advised to be using that in your future SQL journeys.
Good thing to know would be that even though you call the function twice, most modern databases would actually call it only once, so I wouldn't be that much concerned about it.

Oracle 12c Inline View Evaluation

A long time ago in a database far, far away a developer wrote a query in which he/she was reliant on the order in which predicates were written.
For example,
select x
from a, b
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
and a.char_column = b.numeric_column;
(explain plan suggests a to_number conversion will be applied to a.char_column)
I think by chance more than design this "just works" (Oracle 11g). However, the order of the predicates isn't adhered to when running in Oracle 12c, so this query breaks with an invalid number exception. I'm aware that I could try to force 12c to evaluate the predicates in order by using the ORDERED_PREDICATES hint as follows
select /*+ ORDERED_PREDICATES +*/ x
from a, b
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
and a.char_column = b.numeric_column
.. Or cast one of the values using to_char for the comparison. The downside is that to_char could operate on say a million rows. I think the following inline view is probably a better solution. Am I guaranteed that the inline view will be evaluated first?
select x
from b
inner join (
select only_rows_with_numeric_values as numeric_column
from a
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
) c
on c.numeric_column = b.numeric_column;
About predicate order - look at https://jonathanlewis.wordpress.com/2015/06/02/predicate-order-2/
You should rewrite your last query to next using rownum according to doc(https://docs.oracle.com/database/121/SQLRF/queries008.htm#SQLRF52358)
select x
from b
inner join (
select only_rows_with_numeric_values as numeric_column,
rownum
from a
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]')
) c
on c.numeric_column = b.numeric_column;
to suppress query unnesting or simply using hint /*+ no_unnest*/

Oracle join select result

I 've got this problem:
I have a select statement, which is rather time consuming.
I have to join the result with itself.
I want to do something like this:
Select table1.*, table2.Consumption
from (heavy select statement) table1 left outer join
(same heavy statement) table2
on table1."id" = table2."id" and table1."Year" -1 = table2."Year"
I don't want to catch the same data 2 times. I would rather like to do something like table1 table2. Is this possible?
I need this for an application, which executes querys but isn't able to use create or something like this, otherwise i would store the data in a table.
You can use a common table expression (CTE) and materialize the results of the heavy select statement:
WITH heavy AS ( SELECT /*+ MATERIALIZE */ ... (heavy select statemenet) )
Select table1.*, table2.Consumption
from heavy table1 left outer join
heavy table2
on table1."id" = table2."id" and table1."Year" -1 = table2."Year"

How to optimise insert into..select Query?

I have a below insert query:
Insert into MAP_REL_ATTRIBUTE_PHYID
(MAP_RELNAME, MAP_ATTRNAME,MAP_ATTRVALUE,Source_PHYID,MAP_REL_PHYID)
Select a.map_relname,a.MAP_ATTRNAME,a.MAP_ATTRVALUE,a.id,b.ID
from key_attribute a ,
target_attribute b,
map_rel_phyid c
where a.id = c.Source_phyid
and b.id=c.map_rel_phyid
and a.map_relname = 'Connected By'
and a.map_attrname= b.attr_name
and dbms_lob.compare(a.MAP_ATTRVALUE,b.ATTR_VALUE)=0
For DDL and sample data please refer : Check here
This select query returns around 20 million records and thus taking infinite time to insert the data's into the table. I'm trying to optimise this query. I'm new to oracle. Based on the suggestions I found there can be two possibilities to optimise this:
Creating Indexes in which I'm not sure on which columns to index and what kind of indexes I should create.
Using Bulk Processing with BULK COLLECT and FORALL.
I don't know whether the above solutions are correct. Can somebody please suggest me on this? And let me know if there are any other way to improve the performance.
1) Use append hint for insert
2) Do not use any indexes if you select ALL rows from the table
3) Use parallel hints for insert and select (make sure that parallel DML is enabled first)
alter session enable parallel dml;
Insert /*+ APPEND PARALLEL(4) */ into MAP_REL_ATTRIBUTE_PHYID
(MAP_RELNAME, MAP_ATTRNAME,MAP_ATTRVALUE,Source_PHYID,MAP_REL_PHYID)
Select /*+ PARALLEL(4) USE_HASH(a b c) */ a.map_relname,a.MAP_ATTRNAME,a.MAP_ATTRVALUE,a.id,b.ID
from key_attribute a ,
target_attribute b,
map_rel_phyid c
where a.id = c.Source_phyid
and b.id=c.map_rel_phyid
and a.map_relname = 'Connected By'
and a.map_attrname= b.attr_name
and dbms_lob.compare(a.MAP_ATTRVALUE,b.ATTR_VALUE)=0;

Join in Cursor query or two cursors, which is faster?

I need some suggestions for my cursor which is expected to run against millions of records. Here is my cursor query.
CURSOR items_cursor IS -- Brings only records that need to be updated
SELECT a.*, b.* FROM
( SELECT DataId, Name, VersionNum, OwnerId, SubType, LEVEL Lev FROM DTree
START WITH ParentId = startFrom CONNECT BY PRIOR DataId= ABS(ParentId) -- Brings ABS of ParentId
)a,
(
SELECT o.DataId pDataId, o.Permissions OwnerPerm, p.Permissions PublicPerm FROM DTreeAcl o, DTreeAcl p WHERE
o.DataId=p.Dataid AND o.AclType=1 AND p.AclType=3 AND (o.Permissions != ownerPerm OR p.Permissions != publicPerm)
)b
WHERE a.Lev >= 1 AND a.Lev <= 3 AND a.DataId = b.pDataId;
Is it better to get data from second table in another cursor inside the first cursor than join everything in first cursor itself??
A database is built to join. In the vast majority of cases, you're better off letting the database do the join in SQL rather than trying to write your own in PL/SQL.
The only way you'd be better off writing the join in PL/SQL would be if you know that you want a nested loop join and the Oracle optimizer chooses a much less efficient plan. In that case, though, you'd be better off getting the optimizer to give you the plan you want rather than writing a nested loop join in PL/SQL.

Resources