SQL - Get a reference to a table in a subquery - sql

Is it possible to access a table from a subquery?
Select d.table_c.*
from (with table_c as (select *
from table_a)
select *
from table_b
where table_a.id = table_b.id) as d
table_c is inside the subquery of d, I've tried to access it using d.table_c, but it doesn't seem to work.

You cannot use CTE as subquery. But you can write like below.
;WITH table_c
as
(SELECT * FROM table_a)
SELECT *
from table_b b
INNER JOIN table_c c on c.id = b.id

Related

Compare two tables via the three tables SQL

I plan to compare two tables via the three table. my query is as the following
Select count(*)
from tableA a
join tableB b
on a.A_ID =b.A_ID
full join tableC c
on c.B_ID=b.B_ID
where a.A_ID is null or c.B_ID is null
if the count is zore, then the tableA and TableC match, otherwise, these two tables do not match
It takes a long time to run the query. Do we have a way to compare tableA and tableC fast?
Question: How to compare tableA and tableC?
You don't need a FULL JOIN here, you can just join the first two tables, then EXCEPT the third.
SELECT COUNT(*)
FROM (
SELECT b.B_ID, a.A_Name
FROM tableA a
JOIN tableB b ON a.A_ID = b.A_ID
EXCEPT
SELECT c.B_ID, c.B_Name
FROM tableC c
) t;
Note that EXCEPT implies DISTINCT so if you want the number of rows extra in table_A then you need to use WHERE NOT EXISTS
SELECT b.B_ID, a.A_Name
FROM tableA a
JOIN tableB b ON a.A_ID = b.A_ID
WHERE NOT EXISTS (SELECT 1
FROM tableC c
WHERE c.B_ID = b.B_ID AND c.B_Name = a.A_Name
);
If you want to find rows that are in one table but not the other you can use the EXCEPT union in standard SQL
-- Show in A not in B
SELECT * FROM TableA EXCEPT SELECT * FROM TableB
-- Show in A not in C
SELECT * FROM TableA EXCEPT SELECT * FROM TableC
-- Show in B not in A
SELECT * FROM TableB EXCEPT SELECT * FROM TableA
-- Show in B not in C
SELECT * FROM TableB EXCEPT SELECT * FROM TableC
-- Show in C not in A
SELECT * FROM TableC EXCEPT SELECT * FROM TableA
-- Show in C not in B
SELECT * FROM TableC EXCEPT SELECT * FROM TableB

ORA-01799 - need to correct query

Not sure how to rewrite the below query. I’m trying to join table_a to the most recent table_b record. Currently testing for only one ID, but a different criteria on table_a may be added:
Select t.*
from table_a t
left join table_b d on d.id = T.id and d.MOD_DATE IN (SELECT MAX(mod_date) FROM table_b d2 WHERE d2.id = t.id)
where T.id = 123456
Any suggestions?
I think you are looking for something like:
SELECT t.*
FROM table_a t
LEFT JOIN (
SELECT d.*
FROM table_b d
INNER JOIN (
SELECT id
, MAX(mod_date) mod_date_max
FROM table_b d2
GROUP BY id
) db
ON db.id = d.id
AND db.mod_date_max = d.mod_date
) d
ON d.id = T.id
WHERE T.id = 123456
Note that your where clause turns the left join into an inner join.
Also, if you get an error, please post the error message as well, not just its number.
I also found the same could be achieved with the following query:
SELECT * FROM table_a t
WHERE id IN (
SELECT id
FROM (
SELECT id,MAX(MOD_DATE)
FROM table_b
WHERE id = 123456
GROUP BY id
)
)

sql - multiple layers of correlated subqueries

I have table A, B and C
I want to return all entries in table A that do not exist in table B and of that list do not exist in table C.
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
this gives me the first result of entries in A that are not in B. But now I want only those entries of this result that are also not in C.
I tried flavours of:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
where not exists (select 1 from table_C as c
where a.id = c.id)
But that isnt the correct logic. If there is a way to store the results from the first query and then select * from that result that are not existent in table C. But I'm not sure how to do that. I appreciate the help.
Try this:
select * from (
select a.*, b.id as b_id, c.id as c_id
from table_A as a
left outer join table_B as b on a.id = b.id
left outer join table_C as c on c.id = a.id
) T
where b_id is null
and c_id is null
Another implementation is this:
select a1.*
from table_A as a1
inner join (
select a.id from table_A
except
select b.id from table_B
except
select c.id from table_c
) as a2 on a1.id = a2.id
Note the restrictions on the form of the sub-query as described here. The second implementation, by most succinctly and clearly describing the desired operation to SQL Server, is likely to be the most efficient.
You have two WHERE clauses in (the external part of) your second query. That is not valid SQL. If you remove it, it should work as expected:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
not exists (select 1 from table_C as c -- WHERE removed
where a.id = c.id) ;
Tested in SQL-Fiddle (thnx #Alexander)
how about using LEFT JOIN
SELECT a.*
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
LEFT JOIN TableC c
ON a.ID = c.ID
WHERE b.ID IS NULL AND
c.ID IS NULL
SQLFiddle Demo
One more option with NOT EXISTS operator
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM (SELECT b.ID
FROM dbo.test72 b
UNION ALL
SELECT c.ID
FROM dbo.test73 c) x
WHERE a.ID = x.ID
)
Demo on SQLFiddle
Option from #ypercube.Thank for the present;)
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM dbo.test72 b
WHERE a.ID = b.ID
UNION ALL
SELECT 1
FROM dbo.test73 c
WHERE a.ID = c.ID
);
Demo on SQLFiddle
I do not like "not exists" but if for some reason it seems to be more logical to you; then you can use a alias for your first query. Subsequently, you can re apply another "not exists" clause. Something like:
SELECT * FROM
( select * from tableA as a
where not exists (select 1 from tableB as b
where a.id = b.id) )
AS A_NOT_IN_B
WHERE NOT EXISTS (
SELECT 1 FROM tableC as c
WHERE c.id = A_NOT_IN_B.id
)

Avoiding subquery

Fellows,
I have a query as follows:
SELECT A.ID, B.ID, (HUGE SUBQUERY) as HS
FROM TABLE_A JOIN TABLE_B ON A.ID = B.ID
WHERE (HUGE SUBQUERY) > 0
I'd like to avoid repeating the subquery.
Is there any way to rewrite my WHERE as something like
WHERE HS > 0
Or I must turn my subquery into a join?
Look at With clause :
WITH HS AS (Huge subquery)
SELECT A.ID, B.ID, HS
FROM TABLE_A JOIN TABLE_B ON A.ID = B.ID
WHERE HS > 0
OR
SELECT *
FROM
(
SELECT A.ID, B.ID, (HUGE SUBQUERY) as HS
FROM TABLE_A JOIN TABLE_B ON A.ID = B.ID
)
WHERE HS > 0
You could use a CTE:
WITH cteHS AS (
SELECT xxx AS Value
FROM Huge Subquery
)
SELECT A.ID, B.ID, cteHS.Value as HS
FROM TABLE_A, cteHS
JOIN TABLE_B ON A.ID = B.ID
WHERE cteHS.Value > 0

what is wrong with this oracle query?

SELECT *
FROM (SELECT ROWNUM rnum,
query.*
FROM (WITH myQuery AS(
SELECT column_b
FROM table_a a
WHERE a.column_a = 1234)
SELECT b.column_e AS some_column
FROM table_b b,
table_c c,
table_a a
LEFT JOIN table_d d ON c.column_c = d.column_d
JOIN myQuery mq ON a.column_b = mq.column_b
WHERE b.column_b = a.column_b) query)
WHERE rnum > 0
Don't mix ANSI-88 and ANSI-92 JOIN syntax, pick one or the other. Here's your query using ANSI-92 syntax:
WITH myQuery AS (
SELECT column_b
FROM table_a a
WHERE a.column_a = 1234)
SELECT x.*
FROM (SELECT b.column_e AS some_column,
ROWNUM 'rnum'
FROM table_b b
JOIN TABLE_A a ON a.column_b = b.column_b
JOIN myQuery mq ON mq.column_b = a.column_b
JOIN table_c c ON c.? = ?? --need join criteria here
LEFT JOIN table_d d ON c.column_c = d.column_d) x
WHERE x.rnum > 0
Your example lacks what TABLE_C joins on to - hence the ? and ??
I didn't know that WITH clauses can be defined in subqueries - I was sure I'd encountered an error in the past when attempting it in 10g.