getting output of union all without using union all - sql

I have been given a situation to find the common record between 2 tables without using union. I could do it. But I am not able to do 'union all'. I mean I have to find out output of 2 table including duplicate without using union all. is there anyway to do it?
table A has x column and values 1,2,3
and
table B has x column and values 3,4,5
select x from A union select x from B;
o/p 1,2,3,4,5
select x from A union all select x from B;
o/p should be 1,2,3,3,4,5,6(not necessarily in order)
Union output I can achieve through below query
select nvl(a.x,b.x) output from A full outer join B on A.x=b.X order by output;
but I am not able to do union all without using oracle inbuilt union all.

You are too close to your answer.
For union, you used following query where you have a join on column x:
select nvl(a.x,b.x) output from A full outer join B on A.x=b.X order by output;
For union all, you can use join condition which can never be satisfied. It will generate same output as union all.
So you must use following query:
select nvl(a.x,b.x) output from A full outer join B on 1=2 order by output;
Cheers!!

You may get plus points in the interview if you mention some edge cases, here it could be:
Primary Key
If the column in one of the tables is not a primary key (or at leadt unique) the proposed solution for UNION
select nvl(a.x,b.x) output from A full outer join B on A.x=b.X
fails and you have to use DISTINCT
select distinct nvl(a.x,b.x) output from A full outer join B on A.x=b.X
Nullable Column
If the column in one of the tables is nullable the proposed solution for UNION ALL
select nvl(a.x, b.x) x from a full join b on a.x is null or b.x is null
fails. The other solution with on 1=2 works fine.

I have to find out output of 2 table including duplicate without using
union all
select nvl(a.x, b.x) x from a full join b on a.x is null or b.x is null
dbfiddle

Related

Combining two different result set into a single query

Two different queries, produce two different result set.
Query 1:
Select a.customer_name, b.salary, c.manager_name
from
table123 a
left join table456 b on a.id=b.id
left join table789 c on a.id=c.id
Query2:
Select d.prty_id, e.party_val, f.prty_nme
from
table111 d
Left join table222 e on d.id=e.id
Left join table333 f on d.id=f.id
Now I have to write one single query, which will merge this above two query's result set and display one single result set.
Can anyone please help me on this.
Output value I need to insert in a new table whose column will be like below:
customer_name salary manager_name prty_id party_val prty_nme
According to your expected result, you can use UNION or UNION ALL.
The Oracle UNION operator is used to combine the result sets of 2 or more Oracle SELECT statements. It removes duplicate rows between the various SELECT statements.
The Oracle UNION ALL operator is used to combine the result sets of 2 or more SELECT statements. It returns all rows from the query and it does not remove duplicate rows between the various SELECT statements.
Select con1,... , coln
from tab1
where...
union
Select con1,... , coln
from tab2
where...
Just make sure your data types match up.

Does wrapping my Coalesce in a subquery make my query more efficient or does it do nothing?

Lets say I have a query where one field can appear in either Table A or Table B but not both. So to retrieve it I use Coalesce.
Something like
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B on A.C= B.C
Now lets say I want to join another table to that Number field
should I just do
Join Table Z on Z.Z = Coalesce(A.Number,B.Number)
Or is it better to wrap my original table in a query and join on the definite result. So something like
Select * from (
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B on A.C= B.C
) T
left join Table Z on Z.Number= T.Number
Does this make a difference?
if i were joining another table to the result of the first query instead of a sub query i would place the first part in a CTE whenever possible, i believe the performance would be the same as a subquery but CTEs are more readable in my opinion.
with cte1 as
(
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B
on A.C= B.C
)
select *
from cte1 a
Join Table Z
on Z.Z = a.number

Join two tables to get all data

Suppose I have two tables:
Table 1
Col
1
3
4
5
6
9
and Table 2
Col
2
4
6
8
How can I Merge the two tables so I have 1-9 and if a number only appears in one table, the corresponding position in the other table has a null? Thank you.
I'm assuming you want the numbers that actually exist in at least one of the tables, which won't give you a row with 7;
What you're looking for seems to be something like a FULL OUTER JOIN which works in pretty much any RDBMS except MySQL;
SELECT a.col col_a, b.col col_b
FROM Table1 a
FULL OUTER JOIN Table2 b ON a.col = b.col
ORDER BY COALESCE(a.col, b.col);
An SQLfiddle to test with.
Sadly, MySQL does not have FULL OUTER JOIN, so you'll have to do the same operation using a UNION between a LEFT JOIN and a RIGHT JOIN;
SELECT * FROM (
SELECT a.col col_a, b.col col_b
FROM Table1 a
LEFT JOIN Table2 b ON a.col = b.col
UNION
SELECT a.col col_a, b.col col_b
FROM Table1 a
RIGHT JOIN Table2 b ON a.col = b.col
)z
ORDER BY COALESCE(col_a, col_b);
Another SQLfiddle.
If i am not wrong. you need records from both table. (please correct me if i am wrong)
Try following to get data from both tables:
select col from Table1
union
select col from Table2
select col from Table1
union all
select col from Table2
NOTE:
UNION removes duplicate records (where all columns in the results are the same), UNION ALL does not.
There is a performance hit when using UNION vs UNION ALL, since the database server must do additional work to remove the duplicate rows, but usually you do not want the duplicates (especially when developing reports).
You can try this one using union:
SELECT * FROM (SELECT col AS value FROM table1
UNION
SELECT col AS value FROM table2)t1
ORDER BY value
try and post your comments:
Thanks

Issues with SQL Select utilizing Except and UNION All

Select *
From (
Select a
Except
Select b
) x
UNION ALL
Select *
From (
Select b
Except
Select a
) y
This sql statement returns an extremely wrong amount of data. If Select a returns a million, how does this entire statement return 100,000? In this instance, Select b contains mutually exclusive data, so there should be no elimination due to the except.
As already stated in the comment, EXCEPT does an implicit DISTINCT, according to this and the ALL in your UNION ALL cannot re-create the duplicates. Hence you cannot use your approach if you want to keep duplicates.
As you want to get the data that is contained in exactly one of the tables a and b, but not in both, a more efficient way to achieve that would be the following (I am just assuming the tables have columns id and c where id is the primary key, as you did not state any column names):
SELECT CASE WHEN a.id IS NULL THEN 'from b' ELSE 'from a' END as source_table
,coalesce(a.id, b.id) as id
,coalesce(a.c, b.c) as c
FROM a
FULL OUTER JOIN b ON a.id = b.id AND a.c = b.c -- use all columns of both tables here!
WHERE a.id IS NULL OR b.id IS NULL
This makes use of a FULL OUTER JOIN, excluding the matching records via the WHERE conditions, as the primary key cannot be null except if it comes from the OUTER side.
If your tables do not have primary keys - which is bad practice anyway - you would have to check across all columns for NULL, not just the one primary key column.
And if you have records completely consisting of NULLs, this method would not work.
Then you could use an approach similar to your original one, just using
SELECT ...
FROM a
WHERE NOT EXISTS (SELECT 1 FROM b WHERE <join by all columns>)
UNION ALL
SELECT ...
FROM b
WHERE NOT EXISTS (SELECT 1 FROM a WHERE <join by all columns>)
If you're trying to get any data that is in one table and not in the other regardless of which table, I would try something like the following:
select id, 'table a data not in b' from a where id not in (select id from b)
union
select id, 'table b data not in a' from b where id not in (select id from a)

When or why would you use a right outer join instead of left?

Wikipedia states:
"In practice, explicit right outer joins are rarely used, since they can always be replaced with left outer joins and provide no additional functionality."
Can anyone provide a situation where they have preferred to use the RIGHT notation, and why?
I can't think of a reason to ever use it. To me, it wouldn't ever make things more clear.
Edit:
I'm an Oracle veteran making the New Year's Resolution to wean myself from the (+) syntax. I want to do it right
The only reason I can think of to use RIGHT OUTER JOIN is to try to make your SQL more self-documenting.
You might possibly want to use left joins for queries that have null rows in the dependent (many) side of one-to-many relationships and right joins on those queries that generate null rows in the independent side.
This can also occur in generated code or if a shop's coding requirements specify the order of declaration of tables in the FROM clause.
B RIGHT JOIN A is the same as A LEFT JOIN B
B RIGHT JOIN A reads: B ON RIGHT, THEN JOINS A. means the A is in left side of data set. just the same as A LEFT JOIN B
There are no performance that can be gained if you'll rearrange LEFT JOINs to RIGHT.
The only reasons I can think of why one would use RIGHT JOIN is if you are type of person that like to think from inside side out (select * from detail right join header). It's like others like little-endian, others like big-endian, others like top down design, others like bottom up design.
The other one is if you already have a humongous query where you want to add another table, when it's a pain in the neck to rearrange the query, so just plug the table to existing query using RIGHT JOIN.
I've never used right join before and never thought I could actually need it, and it seems a bit unnatural. But after I thought about it, it could be really useful in the situation, when you need to outer join one table with intersection of many tables, so you have tables like this:
And want to get result like this:
Or, in SQL (MS SQL Server):
declare #temp_a table (id int)
declare #temp_b table (id int)
declare #temp_c table (id int)
declare #temp_d table (id int)
insert into #temp_a
select 1 union all
select 2 union all
select 3 union all
select 4
insert into #temp_b
select 2 union all
select 3 union all
select 5
insert into #temp_c
select 1 union all
select 2 union all
select 4
insert into #temp_d
select id from #temp_a
union
select id from #temp_b
union
select id from #temp_c
select *
from #temp_a as a
inner join #temp_b as b on b.id = a.id
inner join #temp_c as c on c.id = a.id
right outer join #temp_d as d on d.id = a.id
id id id id
----------- ----------- ----------- -----------
NULL NULL NULL 1
2 2 2 2
NULL NULL NULL 3
NULL NULL NULL 4
NULL NULL NULL 5
So if you switch to the left join, results will not be the same.
select *
from #temp_d as d
left outer join #temp_a as a on a.id = d.id
left outer join #temp_b as b on b.id = d.id
left outer join #temp_c as c on c.id = d.id
id id id id
----------- ----------- ----------- -----------
1 1 NULL 1
2 2 2 2
3 3 3 NULL
4 4 NULL 4
5 NULL 5 NULL
The only way to do this without the right join is to use common table expression or subquery
select *
from #temp_d as d
left outer join (
select *
from #temp_a as a
inner join #temp_b as b on b.id = a.id
inner join #temp_c as c on c.id = a.id
) as q on ...
The only time I would think of a right outer join is if I were fixing a full join, and it just so happened that I needed the result to contain all records from the table on the right. Even as lazy as I am, though, I would probably get so annoyed that I would rearrange it to use a left join.
This example from Wikipedia shows what I mean:
SELECT *
FROM employee
FULL OUTER JOIN department
ON employee.DepartmentID = department.DepartmentID
If you just replace the word FULL with RIGHT you have a new query, without having to swap the order of the ON clause.
SELECT * FROM table1 [BLANK] OUTER JOIN table2 ON table1.col = table2.col
Replace [BLANK] with:
LEFT - if you want all records from table1 even if they don't have a col that matches table2's (also included are table2 records with matches)
RIGHT - if you want all records from table2 even if they don't have a col that matches table1's (also included are table1 records with matches)
FULL - if you want all records from table1 and from table2
What is everyone talking about? They're the same? I don't think so.
SELECT * FROM table_a
INNER JOIN table_b ON ....
RIGHT JOIN table_c ON ....
How else could you quickly/easily inner join the first 2 tables and join with table_c while ensuring all rows in table_c are always selected?
I've not really had to think much on the right join but I suppose that I have not in nearly 20 years of writing SQL queries, come across a sound justification for using one. I've certainly seen plenty of them I'd guess arising from where developers have used built-in query builders.
Whenever I've encountered one, I've rewritten the query to eliminate it - I've found they just require too much additional mental energy to learn or re-learn if you haven't visited the query for some time and it hasn't been uncommon for the intent of the query to become lost or return incorrect results - and it's usually this incorrectness that has led to requests for me to review why the queries weren't working.
In thinking about it, once you introduce a right-join, you now have what I'd consider competing branches of logic which need to meet in the middle. If additional requirements/conditions are introduced, both of these branches may be further extended and you now have more complexity you're having to juggle to ensure that one branch isn't giving rise to incorrect results.
Further, once you introduce a right join, other less-experienced developers that work on the query later may simply bolt on additional tables to the right-join portion of the query and in doing so, expanding competing logic flows that still need to meet in the middle; or in some cases I've seen, start nesting views because they don't want to touch the original logic, perhaps in part, this is because they may not understand the query or the business rules that were in place that drove the logic.
SQL statements, in addition to being correct, should be as easy to read and expressively concise as possible (because they represent single atomic actions, and your mind needs to grok them completely to avoid unintended consequences.) Sometimes an expression is more clearly stated with a right outer join.
But one can always be transformed into the other, and the optimizer will do as well with one as the other.
For quite a while, at least one of the major rdbms products only supported LEFT OUTER JOIN. (I believe it was MySQL.)
The only times I've used a right join have been when I want to look at two sets of data and I already have the joins in a specific order for the left or inner join from a previously written query. In this case, say you want to see as one set of data the records not included in table a but in table b and in a another set the records not in table b but in table a. Even then I tend only to do this to save time doing research but would change it if it was code that would be run more than once.
In some SQL databases, there are optimizer hints that tell the optimizer to join the tables in the order in which they appear in the FROM clause - e.g. /*+ORDERED */ in Oracle. In some simple implementations, this might even be the only execution plan available.
In such cases order of tables in the FROM clause matters so RIGHT JOIN could be useful.
I think it's difficult if you don't have right join in this case. ex with oracle.
with a as(
select 1 id, 'a' name from dual union all
select 2 id, 'b' name from dual union all
select 3 id, 'c' name from dual union all
select 4 id, 'd' name from dual union all
select 5 id, 'e' name from dual union all
select 6 id, 'f' name from dual
), bx as(
select 1 id, 'fa' f from dual union all
select 3 id, 'fb' f from dual union all
select 6 id, 'f' f from dual union all
select 6 id, 'fc' f from dual
)
select a.*, b.f, x.f
from a left join bx b on a.id = b.id
right join bx x on a.id = x.id
order by a.id