Oracle - Join operation with table aliases - sql

I have 3 Table A B and C. I want to firstly process Table A and B to create a table 'AB' then join the result of that to C. Here is what I have in mind:
select C.number, C.class, AB.name
from C,
(select A.name, A.number
from A
FULL OUTER JOIN B
ON A.number = B.number) AB
FULL OUTER JOIN AB
ON AB.number = C.number
However it doesn't seem to be working. Now I am not sure if giving the result of A&B an alias works in Oracle DB. How should this be done the correct way?

SELECT C.number,
C.class,
AB.name
FROM C
FULL OUTER JOIN
(SELECT A.name,
A.number
FROM A
FULL OUTER JOIN B
ON A.number = B.number) AB
ON AB.number = C.number

Related

Pull columns from series of joins in SQL

I am kind of stuck at one problem at my job where I need to pull 2 cols from base table and 1 column from a series of joins.
Please note that, I can not provide real data so I am using dummy column/table names and there are 100s of columns in real project.
Select A.Name,B.Age, D.Sal
From A Left join B on A.iD=B.id and B.Date=CURRENT_DATE
(/* join A and B table and return distinct column which is B.XYZ)
inner join C on C.iD=B.XYZ
(/* join B and C take C.YYY column for next join */)
inner join D on D.id=C.YYY
(/* Take out the D.Sal column from this join */) where A.Dept='IT'
I have written this query but it is taking forever to run because B.XYZ column has a lot of duplicates. how can I get distinct of B.XYZ column from that join.
For Joining Table B, you first get a distinct table of the columns you need from B then join.
SELECT
A.Name,
B.Age,
D.Sal
From A
LEFT JOIN ( -- Instead of all cols (*), just id, Date, Age and xyz might do
SELECT DISTINCT * FROM B
) B ON A.iD = B.id AND B.Date = CURRENT_DATE
--(/* join A and B table and return distinct column which is B.XYZ */)
INNER JOIN C ON C.iD = B.XYZ
--(/*join B and C take C.YYY column for next join */)
INNER JOIN D ON D.id = C.YYY
--(/* Take out the D.Sal column from this join */)
WHERE A.Dept='IT'
You say you get the same rows multifold, because for a b.id, date and age you get the same xyz more than once, or so I understand it.
One option is to join with a subquery that gets the distinct data:
SELECT a.name, b.age, d.sal
FROM a
LEFT JOIN
(
SELECT DISTINCT id, date, age, xyz FROM b
) dist_b ON dist_b.id = a.id and dist_b.date = CURRENT_DATE
INNER JOIN c ON c.id = dist_b.xyz
INNER JOIN d ON d.id = c.yyy
WHERE a.dept = 'IT';
Of course you can even move the date condition inside the subquery:
SELECT a.name, b.age, d.sal
FROM a
LEFT JOIN
(
SELECT DISTINCT id, age, xyz FROM b WHERE date = CURRENT_DATE
) dist_b ON dist_b.id = a.id
INNER JOIN c ON c.id = dist_b.xyz
INNER JOIN d ON d.id = c.yyy
WHERE a.dept = 'IT';
Your LEFT OUTER JOIN doesn't work by the way. As you are inner joining the following tables, a match must exists, so your outer join becomes an inner join. For the outer join to work you would have to outer join the following tables, too.

How to get rows from one or another joined table and then further to more joined tables depending on which first two tables were joined

I have three tables (a, b, c) and two (b and c) need to be joined to get detail data from the first table a. But the problem is that I need to do this in one query.
If I join both tables in the same query than no records are found as detail data is either in b or c, but never in both.
To further complicate things, I need to further join other tables (b2, c2) based on with the record found is from b or c.
I am using MS SQL.
The query I have now is:
select a.*, b.name1, c.name1, b2.url, c2.url
left join b on a.aID = b.aID
left join c on a.aID = c.aID
inner join b2 on b.bID = b2.bID
inner join c2 on c.cID = c2.cID
where a.date > '9/1/2016'
I searched for a few days, but no one seems to need to go after the fourth and fifth tables in the query and so couldn't find any similar answer
Is there any way to do this? Performance is not an issue as the number of records will be less than 1,000 after executing a where clause that will always limit the records from table a.
A series of left joins with inner joins as subqueries should do the trick. The subqueries pull the b/b2 and c/c2 data together for reference in the left joins with a:
select a.*, b.name1, c.name1, b2join.url, c2join.url
FROM a
LEFT JOIN b
on a.aID = b.aID
LEFT JOIN c
on a.aID = c.aID
LEFT JOIN
(SELECT b.aID, b.bID, b2.url
FROM b
INNER JOIN b2
on b.bID = b2.bID) as b2join
on b2join.aID = a.aID
LEFT JOIN
(SELECT c.aID, c.cID, c2.url
FROM c
INNER JOIN c2
on c.cID = c2.cID) as c2join
on c2join.aID = a.aID
I think a Left Join will do it, at least for the first part:
select a.*, b.name1, c.name1
left join b on a.aID = b.aID
left join c on a.aID = c.aID
where a.date > '9/1/2016'
You will get c.name1 null when data is in b table, and b.name1 will be null when data is in c table.
For the other two joins and not sure but left join could also work.
I think, it is more simple and brief way to get the same result:
select a.*, b.name1, c.name1, b2join.url, c2join.url
FROM a
LEFT JOIN b on a.aID = b.aID
LEFT JOIN c on a.aID = c.aID
LEFT JOIN b as b2join on b2join.bID = b.bID
LEFT JOIN a as c2join on c2join.cID = c.cID

What is wrong with the following SQL left join?

I have 5 tables: A, B, C, D, E
A: {ID, Value, GroupID, FilterID, In_Date}
B: {ID, Description, Out_Date, From_Date }
C: {ID, Category}
D: {GroupID, GroupName}
E: {FilterID, FilterName}
There could be missing IDs in B and C as a result, I'm trying to do a LEFT JOIN to get the required info. In my dataset, I've explicitly added a row in A with ID that's not in B or C. I expect it to be picked up in the following query, but it doesn't happen. I believe I'm going wrong in the WHERE clause due to null values in B and C.
SELECT A.Value, A.Group, B.Description, C.Category, D.GroupName, E.FilterName
FROM A LEFT JOIN B ON A.ID = B.ID
LEFT JOIN C ON A.ID = C.ID,
D,E
WHERE
B.Out_Date>A.In_Date,
A.GroupID=D.GroupID,
A.FilterID=E.FilterID
How can I fix this to retrieve the fields I want with null values when the ID is not in B or C , but in A?
1) Don't mix old comma separated join syntax with modern explicit join syntax!
2) When left join, put the right side table's conditions in the ON clause to get true left join behavior. (When in WHERE you get inner join result.)
SELECT A.Value, A.Group, B.Description, C.Category, D.GroupName, E.FilterName
FROM A LEFT JOIN B ON A.ID = B.ID AND B.Out_Date > A.In_Date
LEFT JOIN C ON A.ID = C.ID
JOIN D ON A.GroupID = D.GroupID
JOIN E ON A.FilterID = E.FilterID
Value and Group are reserved words in ANSI SQL, so you may need to delimit them, as "Value" and "Group".
First point: You shouldn't mix join syntaxes, just use explicit syntax.
Because of your where clause, you effectively turn your left joins in inner joins. You are probably looking for:
SELECT A.Value, A.Group, B.Description, C.Category, D.GroupName, E.FilterName
FROM A
LEFT JOIN B
ON A.ID = B.ID
AND B.Out_Date > A.In_Date
LEFT JOIN C
ON A.ID = C.ID
INNER JOIN D
ON A.GroupID = D.GroupID
INNER JOIN E
ON A.FilterID = E.FilterID
You can use this query for your problem.
SELECT A.Value, A.Group, B.Description, C.Category, D.GroupName, E.FilterName
FROM A
LEFT JOIN B
ON A.ID = B.ID
AND B.Out_Date > A.In_Date
LEFT JOIN C
ON A.ID = C.ID
LEFT JOIN D
ON A.GroupID = D.GroupID
LEFT JOIN E
ON A.FilterID = E.FilterID
Here is your table details
A: {ID, Value, GroupID, FilterID, In_Date}
B: {ID, Description, Out_Date, From_Date }
C: {ID, Category}
D: {GroupID, GroupName}
E: {FilterID, FilterName}
now you try to retrieve data using left join
so you try the flowing script
SELECT A.Value, A.Group, B.Description, C.Category, D.GroupName,E.FilterName from A left join B on A.ID=B.ID
left Join C on A.ID=C.ID
Left Join D on A.GroupID=D.GroupID
Left Join E on A.FilterID=E.FilterID
where B.Out_Date>A.In_Date
I hope this is help full for you.

Join 3 Tables in SQL Server 2008

I'm trying to join 3 tables together with an inner join. Tables prod_num and usrs are relted by usr_Id and tables usrs and usr_Data are related by usr_Num. So tables 1 and 3 are not related in between so I want to realte the result of joining 1 and 2 with table 3 this is what im trying to do:
USE Puzzle
SELECT a.Name, a.Id, b.Id, c.Email
FROM prod_num a INNER JOIN usrs b
ON a.usr_Num = b.usr_Num<br>FROM usrs b INNER JOIN usr_Data c
ON b.usr_Id = c.usr_Id
How can I do a Join from a result of a previous Join?
You should only use one FROM keyword because JOINs are part of the FROM clause,
SELECT a.Name,
a.Id,
b.Id,
c.Email
FROM prod_num a
INNER JOIN usrs b
ON a.usr_Num = b.usr_Num
INNER JOIN usr_Data c
ON b.usr_Id = c.usr_Id
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Try this:
USE Puzzle
SELECT a.Name, a.Id, b.Id, c.Email
FROM prod_num a
INNER JOIN usrs b ON a.usr_Num = b.usr_Num
INNER JOIN usr_Data c ON b.usr_Id = c.usr_Id
You have an extra FROM clause between your JOIN statements.
You can do this:
USE Puzzle
SELECT
a.Name,
a.Id,
b.Id,
c.Email
FROM prod_num a
INNER JOIN usrs b ON a.usr_Num = b.usr_Num
INNER JOIN usr_Data c ON b.usr_Id = c.usr_Id

Simulate a left join without using "left join"

I need to simulate the left join effect without using the "left join" key.
I have two tables, A and B, both with id and name columns. I would like to select all the dbids on both tables, where the name in A equals the name in B.
I use this to make a synchronization, so at the beginning B is empty (so I will have couples with id from A with a value and id from B is null). Later I will have a mix of couples with value - value and value - null.
Normally it would be:
SELECT A.id, B.id
FROM A left join B
ON A.name = B.name
The problem is that I can't use the left join and wanted to know if/how it is possible to do the same thing.
you can use this approach, but you must be sure that the inner select only returns one row.
SELECT A.id,
(select B.id from B where A.name = B.name) as B_ID
FROM A
Just reverse the tables and use a right join instead.
SELECT A.id,
B.id
FROM B
RIGHT JOIN A
ON A.name = B.name
I'm not familiar with java/jpa. Using pure SQL, here's one approach:
SELECT A.id AS A_id, B.id AS B_id
FROM A INNER JOIN B
ON A.name = B.name
UNION
SELECT id AS A_id, NULL AS B_id
FROM A
WHERE name NOT IN ( SELECT name FROM B );
In SQL Server, for example, You can use the *= operator to make a left join:
select A.id, B.id
from A, B
where A.name *= B.name
Other databases might have a slightly different syntax, if such an operator exists at all.
This is the old syntax, used before the join keyword was introduced. You should of course use the join keyword instead if possible. The old syntax might not even work in newer versions of the database.
I can only think of two ways that haven't been given so far. My last three ideas have already been given (boohoo) but I put them here for posterity. I DID think of them without cheating. :-p
Calculate whether B has a match, then provide an extra UNIONed row for the B set to supply the NULL when there is no match.
SELECT A.Id, A.Something, B.Id, B.Whatever, B.SomethingElse
FROM
(
SELECT
A.*,
CASE
WHEN EXISTS (SELECT * FROM B WHERE A.Id = B.Id) THEN 1
ELSE 0
END Which
FROM A
) A
INNER JOIN (
SELECT 1 Which, B.* FROM B
UNION ALL SELECT 0, B* FROM B WHERE 1 = 0
) B ON A.Which = B.Which
AND (
A.Which = 0
OR (
A.Which = 1
AND A.Id = b.Id
)
)
A slightly different take on that same query:
SELECT A.Id, B.Id
FROM
(
SELECT
A.*,
CASE
WHEN EXISTS (SELECT * FROM B WHERE A.Id = B.Id) THEN A.Id
ELSE -1 // a value that does not exist in B
END PseudoId
FROM A
) A
INNER JOIN (
SELECT B.Id PseudoId, B.Id FROM B
UNION ALL SELECT -1, NULL
) B ON A.Which = B.Which
AND A.PseudoId = B.PseudoId
Only for SQL Server specifically. I know, it's really a left join, but it doesn't SAY LEFT in there!
SELECT A.Id, B.Id
FROM
A
OUTER APPLY (
SELECT *
FROM B
WHERE A.Id = B.Id
) B
Get the inner join then UNION the outer join:
SELECT A.Id, B.Id
FROM
A
INNER JOIN B ON A.name = B.name
UNION ALL
SELECT A.Id, NULL
FROM A
WHERE NOT EXISTS (
SELECT *
FROM B
WHERE A.Id = B.Id
)
Use RIGHT JOIN. That's not a LEFT JOIN!
SELECT A.Id, B.Id
FROM
B
RIGHT JOIN A ON B.name = A.name
Just select the B value in a subquery expression (let's hope there's only one B per A). Multiple columns from B can be their own expressions (YUCKO!):
SELECT A.Id, (SELECT TOP 1 B.Id FROM B WHERE A.Id = B.Id) Bid
FROM A
Anyone using Oracle may need some FROM DUAL clauses in any SELECTs that have no FROM.
You could use subqueries, something like:
select a.id
, nvl((select b.id from b where b.name = a.name), "") as bId
from a
you can use oracle + operator for left join :-
SELECT A.id, B.id
FROM A , B
ON A.name = B.name (+)
Find link :-
Oracle "(+)" Operator
SELECT A.id, B.id
FROM A full outer join B
ON A.name = B.name
where A.name is not null
I'm not sure if you just can't use a LEFT JOIN or if you're restricted from using any JOINS at all. But as far as I understand your requirements, an INNER JOIN should work:
SELECT A.id, B.id
FROM A
INNER JOIN B ON A.name = B.name
Simulating left join using pure simple sql:
SELECT A.name
FROM A
where (select count(B.name) from B where A.id = B.id)<1;
In left join there are no lines in B referring A so 0 names in B will refer to the lines in A that dont have a match
+ or A.id = B.id in where clause to simulate the inner join