I have this SQL statement where there are many not exists clauses. Is there a way to rewrite the conditions and avoid table same table scan?
select col1,
col2,....,colN
from tab1
join <some join conditions> tab3
where not exists (select null
from tab2 p
where <some conditions eg: name = 'ABC'>
and tab1.some_col = tab2.some_col)
and not exists (select null
from tab2 p
where <some conditions eg: last_name = 'XYZ'>
and tab1.some_col = tab2.some_col)
and not exists (select null
from tab2 p
where <some conditions eg: country = 'PQR'>
and tab1.some_col = tab2.some_col)
and not exists (select null
from tab2 p
where <similar conditions>
and tab1.some_col = tab2.some_col)
and not exists (select null
from tab2 p
where <similar conditions>
and tab1.some_col = tab2.some_col);
In the above query there are more not exists of similar fashion. since the not exists clause has the same table to be validated against is there a way to club these not exists into a single kind of sub query.
You may OR together the various conditions:
SELECT col1, col2,. .., colN
FROM tab1 t1
INNER JOIN tab3 t3
<join conditions>
WHERE NOT EXISTS (SELECT 1
FROM tab2 p
WHERE
(name = 'ABC' OR
last_name = 'XYZ' OR
country = 'PQR') AND
t1.some_col = p.some_col);
You can use in ( 'ABC','XYZ',PQR'...) like below
select col1,
col2,....,colN
from tab1
join <some join conditions>
where not exists (select null
from tab2 p
where <some conditions eg: name in( 'ABC','XYZ',PQR')>
and tab1.some_col = tab2.some_col
)
Related
I'm creating 1 temp table (temp1) using table1.
and I want to check if data from temp table is present in table1 and table2.
table1 and table2 have same columns.
It's difficult to assess exactly what you need without further detail, but you could try a LEFT JOIN and a COUNT here to indicate whether there are any matching rows (whereby anything over 0 indicates matching rows)
SELECT
COUNT(*) AS matching_rows
FROM
(
SELECT
1 AS 'ColumnA'
) AS T1
LEFT OUTER JOIN
(
SELECT
2 AS 'ColumnA'
) AS T2
ON T1.ColumnA = T2.ColumnA
WHERE
T2.ColumnA IS NOT NULL
You can also use an INNER JOIN for this:
SELECT
COUNT(*) AS matching_rows
FROM
(
SELECT
1 AS 'ColumnA'
) AS T1
INNER JOIN
(
SELECT
2 AS 'ColumnA'
) AS T2
ON T1.ColumnA = T2.ColumnA
select *
from table1 t1,
table2 t2,
table3 t3
where t2.parent_id = t1.row_id
and t2.xyz is not null
and (
select count(*)
from table3
where xyz = t2.row_id
) = 0;
Will it work?
I am using the alias t2 within my subquery.
My requirement is to check is to specify condition in where clause such that there is no record present in table3 where column xyz of table3 is stored as row_id of table2.
You can use NOT EXISTS to assert that there is no row returned from the subquery. Use modern explicit join syntax instead of comma based legacy syntax. No need to join table3 outside (you were making a cross join effectively).
select *
from table1 t1
join table2 t2 on t2.parent_id = t1.row_id
where t2.xyz is not null
and not exists (
select 1
from table3
where xyz = t2.row_id
);
I have SELECT statement with LEFT JOIN and joined tables are sub-queries. And Oracle could not recognize alias of the first sub-query in the second one. It works for DB2 but does not work for Oracle.
How I can implement it or rewrite my query?
SELECT *
FROM
(SELECT E.C3 AS COLUMN3
, E.C4 AS COLUMN4
FROM TBL_1 D
, TBL_2 E
WHERE D.C6 = E.C6 ) B
LEFT JOIN TABLE
(SELECT C.C1
FROM TBL_3 C
WHERE
C.C7 = 'hello'
AND B.C3 = C.C8
UNION ALL
SELECT C.C1
FROM TBL_3 C
WHERE
C.C7 = 'world'
AND B.C4 = C.C8
) A
ON 1 = 1
Oracle error message:
ORA-00904: "B"."C3": invalid identifier
You can simplify this query to the following, removing the sub-queries:
Select A.Col1, B.Col2
From tbl_AJoin A
Left Join tbl_BJoin B On A.col1 = B.col1
You have a syntax error. This:
select * from (select col1 from tbl_Ajoin) A
left join table (select col2 from tbl_Bjoin where A.col1 = tbl_Bjoin.col1) B
ON 1 = 1
should be this:
select * from (select col1 from tbl_Ajoin) A
left join (select col2 from tbl_Bjoin where A.col1 = tbl_Bjoin.col1) B
ON 1 = 1
or more specifically, this:
left join table (select
should not have the word table. It should be this:
left join (select
I'm working with an Oracle database, and i have a query where i have to perform a join of 7 different tables.
Now, my problem is, i need to get rows that fulfill the requirements of the join (obviously) but even if they don't match the conditions of the last join i need to get the rows from the first 6 tables.
I can't do a left outer join, so what alternatives do i have?
The code looks something like this:
with
tmp as (select col1, col2, col3, col4, row_number() over (partition by col1 order by col2 desc) rn
from
(select /*+ MATERIALIZE */
col1, col2, col3, col4
from
table1
where
col3 in ('A','R','F') and
somedate >= sysdate-720 and
col5 is null
and col1<> '0000000000'))
select /*+ use_hash(a,b,c,d,e,f,g,h) */
b.col5,
a.col1,
d.col6,
e.col7,
c.col8 ,
(CASE when f.col9= 'B' then 'Foo' else 'Bar' END) as "col9",
a.col2,
a.col3,
h.col10
from tmp a
join table2 b on
a.col1= b.col1 and
a.col4=b.col4 and
b.col11='P' and
(b.otherDate>= sysdate OR b.otherDate is null) and
b.col5 is null
join table3 c on
b.col12 = c.col12 and
(c.otherDate is null or b.otherDate >= sysdate) and
c.col5 is null
join table4 d on
a.col1= d.col1 and
d.col13 in ('R','A','F') and
d.col5 is null
join table5 e on
e.col1=b.col1 and
e.col14=d.col14 and
d.col6=e.col6 and
d.col15 = e.col15 and
e.col5 is null
join table6 f on
f.col4= a.col4 and
f.col5 is null
join table7 g on
g.col16= case when f.col15 is null then null else f.col15 end
and g.col5is null
and (g.otherDate is null or g.otherDate >= sysdate)
join table8 h on
h.col17= g.col17
and (h.otherDate >= sysdate or h.otherDate is null)
and h.col5 is null
and a.rn=1;
I'm not going to attempt to work with your actual query, but in principle you could change:
select tab1.col1, tab2.col2, tab3.col3
from tab1
join tab2 on tab2.fk = tab1.pk
join tab3 on tab3.fk = tab2.pk
into:
select tab1.col1, tab2.col2, tab3.col3
from tab1
join tab2 on tab2.fk = tab1.pk
left join tab3 on tab3.fk = tab2.pk
which you could replace (in your out-joins-not-allowed world) with:
with tmp as (
select tab1.col1, tab2.col2, tab3.pk
from tab1
join tab2 on tab2.fk = tab1.pk
)
select tmp.col1, tmp.col2, tab3.col3
from tmp
join tab3 on tab3.fk = tmp.pk
union all
select tmp.col1, tmp.col2, null as col3
from tmp
where not exists (
select null from tab3
where tab3.fk = tmp.pk
)
Which is quite ugly - I've minimised the repetition with a CTE, but even so not nice - and is likely to not perform as well as the outer join would.
Of course, without knowing why you can't use an outer join, I don't know if there are other restrictions that would make this approach unacceptable as well...
Is it possible to write a sql query where you know you have to use the left outer join..but cannot or are not allowed to use the "outer join" Key Word
I have two table sand want to get rows with null vaues from the left table ...this is pretty simple ...but am not supposed to use the key word....outer join....I need to right the logic for outer join myself
SELECT Field1
FROM table1
WHERE id NOT IN (SELECT id FROM table2)
SELECT Field1
FROM table1
WHERE NOT EXISTS (SELECT * FROM table2 where table2.id = table1.id)
This is something people do but it is deprecated and it does not currently work correctly (it sometimes will return a cross join instead of a left join) so it should NOT be used. I'm telling this only so you avoid using this solution.
SELECT Field1
FROM table1, table2 where table1.id *= table2.id
;WITH t1(c,d) AS
(
SELECT 1,'A' UNION ALL
SELECT 2,'B'
),t2(c,e) AS
(
SELECT 1,'C' UNION ALL
SELECT 1,'D' UNION ALL
SELECT 3,'E'
)
SELECT t1.c, t1.d, t2.c, t2.e
FROM t1, t2
WHERE t1.c = t2.c
UNION ALL
SELECT t1.c, t1.d, NULL, NULL
FROM t1
WHERE c NOT IN (SELECT c
FROM t2
WHERE c IS NOT NULL)
Returns
c d c e
----------- ---- ----------- ----
1 A 1 C
1 A 1 D
2 B NULL NULL
(Equivalent to)
SELECT t1.c, t1.d, t2.c, t2.e
FROM t1
LEFT JOIN t2
ON t1.c = t2.c
For SQL Server, you can just use LEFT JOIN - the OUTER is optional, just like INTO in an INSERT statement.
This is the same for all OUTER JOINs.
For an INNER JOIN you can just specify JOIN with no qualifiers and it is interpreted as an INNER JOIN.
This will give you all the rows in table A that don't have a matching row in table B:
SELECT *
FROM A
WHERE NOT EXISTS (
SELECT 1
FROM B
WHERE A.id = B.id
);
Returns all the matching rows from both tables:
SELECT a.*,b.* FROM table_a a, table_b b
WHERE a.key_field = b.key_field
Potential drawback is non-matches will be skipped.