Select distinct or select distinct from subquery - oracle

Which is better than the two queries below in terms of performance? The difference is that the first query uses the distinct directly, and the second one has the first query as the inner query (the records are already filtered before the distinct)
(this is oracle)
select distinct t1.f1, t2.f2
from t1, t2
where ...
select distinct f1, f2
from
select *
from t1, t2
where ...

If the subquery expresses the same logic, then they are the same. The subquery will be eliminated by a transformation in the optimiser.

Related

USING multiple 'OR' conditions in JOIN component in Oracle data Integrator 12c

I want to use multiple 'OR' conditions in JOIN component in Oracle data Integrator 12c.
Conditions to be taken care when doing the above task is:
Say table T1 and T2, I need to take left outer join on T1(i.e. I need all the records from T1 for multiple satisfied join conditions specified in JOIN component in ODI 12c)
For example:
a. For table T1, T2: say conditions c1, c2, c3. T1 Left outer join T2.
b. I want to get the data in table say T3: Ensuring all records from T1 PLUS all records from T2 for all the conditions satisfied(namely c1,c2,c3).
Sample query:
select T1.*
from T1 LEFT OUTER JOIN T2
ON (C1 OR C2 OR C3);
Kindly help me on this at the earliest.
Thanks in advance!
You can try either query both will get you all the rows from T1 that either matched with T2 columns respectively or didn't have any match with T2.
Using UNION
SELECT DISTINCT *
FROM (
SELECT T1.*
FROM T1
LEFT OUTER JOIN T2 ON T1.day = T2.day
UNION
SELECT T1.*
FROM T1
LEFT OUTER JOIN T2 ON T1.month = T2.month
UNION
SELECT T1.*
FROM T1
LEFT OUTER JOIN T2 ON T1.yearly = T2.yearly
) as T3;
Using OR (NOTE: displaying T2 columns just to show that LEFT JOIN is working on each condition)
SELECT T1.*, T2.*
FROM T1
LEFT OUTER JOIN T2 ON
(T1.day = T2.day OR T1.month = T2.month OR T1.yearly = T2.yearly)
Sample Run
I have 4 records in T1 and 3 records in T2. Records in T1 are such that 3 rows
match with exactly 1 column in T2 and 4th row doesnt match any records in T2.
Output of both the queries gets what you need.

WHERE clause to restrict rows left join

I don't understand why these two queries below fetch different count. Case 1 below fetches more rows while Case 2 fetches fewer rows. If the where clause is put outside, fewer records are fetched.
Case 1
SELECT COUNT(1)
FROM (
SELECT *
FROM (SELECT * FROM TABLE1 WHERE COL1 = 123) A
LEFT JOIN TABLE2 B ON B.COL2=A.COL4
LEFT JOIN TABLE3 C ON C.COL3=B.COL2
)
Case 2
SELECT COUNT(1)
FROM (
SELECT *
FROM (SELECT * FROM TABLE1 ) A
LEFT JOIN TABLE2 B ON B.COL2=A.COL4
LEFT JOIN TABLE3 C ON C.COL3=B.COL2
)
WHERE COL1 = 123
Theoretical explanation:
Consider a left outer join of tables A and B. A condition (filter) on table B has different effects if it is in the join condition (ON clause) vs. in the WHERE clause. EDIT: The filter on B being in the ON condition is equivalent to replacing B with a subquery where the filter is applied first (similar to the OP's example).
If it's in the ON clause, then the rows in table B are filtered for that condition, and then the left join is performed. Then the result of the query will include rows from A (with NULL for the B side) whenever there are no rows in B that satisfy the filter and match the row in A on the join condition.
On the other hand, if the filter on B comes later in the execution, in a WHERE clause, then the left join is performed first. Only then is the WHERE clause applied. The WHERE clause is very likely (depending on the conditions on B) to reject all the rows from A that didn't have a matching row in B - because for such rows, all the values from B are NULL.
In your case, assuming COL1 only exists in table B, then the condition COL1=123 in a WHERE clause will effectively cause the left join to produce the same result as an inner join: any rows from A that didn't have a match in B will come from the left join with COL1 as NULL, so they will fail the filter condition. When you put COL1=123 in the ON clause, that check is done BEFORE the "outer join" operation.

How to use select with if condition with different tables in oracle rather than writing a function or stored procedure?

My requirement is to get a report from a complex query using a if sentence.
If a flag=0 I must perform set of select statements, if the flag = 1 I must perform another set of select statements from another table,
Is there any way I can achieve this in a query rather than writing a function or stored procedure?
Eg:
In SQL I do this
if flag = 0
select var1, vari2 from table1
else
select var1, vari2, var3, vari4 from table2
Is this possible ??
There is no if in SQL - there is the case expression, but it is not quite the same thing.
If you have two tables, t1 and t2, and flag is in a scalar table t3 ("scalar" means exactly one column, flag, and with exactly one row, with the value either 0 or 1), you can do what you want but only if t1 and t2 have the same number of columns, with the same data types (and, although not required by syntax, this would only make sense if the columns in t1 and t2 have the same business meaning). Or, at least, if you plan to select only some columns from t1 or from t2, the columns you want to select from either table should be equal in number, have the same data type, and preferably the same business meaning.
For example: t1 and t2 may be employee tables, perhaps for two companies that just merged. If they both include first_name, last_name, date_of_birth and you just want to select these three columns from either t1 or t2 based on the flag value (even if t1 has other columns, not present in t2), you can do it. Same if t1 or t2 or both is not a single table, but the result of a more complicated query. The principle is the same.
The way you can do it is with a UNION ALL, like this:
select t1.col1, t1.col2, ...
from t1 cross join t3
where t3.flag = 0
UNION ALL
select t2.col1, t2.col2, ...
from t2 cross join t3
where t3.flag = 1
;

Difference between standard outer left join and join using select

Is there any difference between these two statements:
-- Statement 1:
SELECT *
FROM Table1 t1
LEFT OUTER JOIN TABLE2 t2 on t1.id = t2.id
and
-- Statement 2:
SELECT *
FROM Table1 t1
LEFT OUTER JOIN (SELECT id, a, b, c FROM Table2) t2 on t1.id = t2.id
I'm not an expert but statement 2 just looks like poorly written sql, and like it would take much longer. I'm attempting to optimize a code block and it has many joins like the second one. Are they technically the same and I can just replace with the standard join statement 1?
Thanks!
Ps. This is Oracle, and working with 100's of millions of rows.
PSS. I'm doing my own detective work to figure out if they are the same, and time differences, was hoping an expert could explain if there is a technical difference what it is.
They are not same queries, with the lack of a criteria in the subquery that depends on whether the all columns and all column names of the TABLE2 is involved in the subquery. If the subquery involves all of the column names of the TABLE2 in the select list then they are the same query and the subquery is unnecessary. With subquery I refer to the part with a select statement after the join statement in the parens.
The first one uses the TABLE2 with its all columns, all those columns will be available in the result set where the criteria met.
However in the second one the table you make the JOIN is not the TABLE2 of yours but a table with just columns from TABLE2 specified in the subquery's SELECT list, namely id, a, b, and c. But it will have all the rows after this subquery since no criteria is enforced on it by a WHERE clause in the subquery.
You will have same number of rows with only selected columns participating from the TABLE2.
The second one is not necessarily the poorly written one. You could have a criteria to met before you JOIN to the TABLE2.

Oracle query taking too much of time when I use rownum

If I execute below query, it is returning results very fast.
(select * from
select * from t1, t2 t3, t4 where ...(inner/outer join) group by ...) order by create_date desc)
How ever If I use ROWNUM like below, it is taking too much of time.
select * from (select * from
select * from t1, t2 t3, t4 where ...(inner/outer join) group by ...) order by create_date desc) where rownum =1
could you please let me know why t is taking too much of time. How I can get latest date record.
Are you see all returning results for first query or are you see first few rows and you don't wait last row?
I think in second query, first works internal query and after the condition "rownum =1" check all result records

Resources