SQL condition on unioned tables - sql

I'm trying to execute a query with union and then put an additional condition on the result. Basically, I want to have something like
SELECT * FROM (A UNION B) WHERE condition
Is this possible to do? When I try to execute
SELECT * FROM (A UNION B)
SQL Management Studio complains about the closing bracket:
Incorrect syntax near ')'.

SELECT *
FROM ( SELECT * FROM A
UNION
SELECT * FROM B
) temp
WHERE condition

Here is the correct syntax:
SELECT *
FROM (select from A
UNION
select from B
) ab
WHERE condition;
I agree that the original syntax "looks right" for a from statement, but SQL doesn't allow it. Also, you need an alias on the subquery (requirement of SQL Server). Finally, you might consider using union all, if you know there are no duplicates in tables.

how about with CTE:
with tbl as (
select * from a
union
select * from b)
select * from tbl where condition

Use alias for derived table
SELECT * FROM (select * from A UNION select * from B) as t WHERE condition

Related

How to add union data in table?

Thanks in advance !!
I want to get below data in separate table with column how can we achieved this.
From my reading of your question, you would like the results of that SELECT statement put into a new table?
Firstly, I'm assuming your original SQL works as a SELECT statement - e.g., all those tables have the same structure. Note that you can simplify the unions, but I haven't done so here, to keep the key part of the answer (saving the data) as the main focus.
To save the data into another table, you can either create a table first and make that into an insert, or just use 'SELECT INTO' within the main SELECT.
If you are happy with the columns being automatically created, the 'SELECT INTO' version will create columns (e.g., you do not need to specify the columns in a CREATE TABLE statement). However, when you run the SELECT INTO, it does create the table. Therefore if you want to insert further values, you need to specify the column list (or have matching column lists).
SELECT INTO version
select *
INTO #Temp -- Added This row
from
( select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
) A
except
select * from
( select * from #ONEYRCON
union all
select * from #OTHERYRCON
) B
INSERT INTO version
CREATE TABLE #Temp (<your fields here to match the SELECT statement>)
INSERT INTO #Temp
select * from
( select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
) A
except
select * from
( select * from #ONEYRCON
union all
select * from #OTHERYRCON
) B
Set operators are evaluated from top to bottom so there only needs to be 1 subquery. Something like this
select ab.* into #Temp
from (select * from #OneyearExpiry
union all
select * from #OtherYearExpiry
except
select * from #ONEYRCON
except
select * from #OTHERYRCON) ab;

SQL statement to return non-intersection records

I was recently asked this question and was a little stumped so I want to ask the experts...
Given two tables A & B, I want to return all the values from A and B that do not overlap. Think of two overlapping circles; how do we return all the data that is NOT in the overlapping center section? And, I had to use ANSI Standard SQL rather than Oracle syntax.
Assuming we want everything exclusive to both A & B, my answer was
select *
from A
cross join B
minus
(select a.common_column from a
intersect
select b.common_column)
Does this look correct, or even close? If it is correct, is there a more efficient way to do this?
BTW - my solution was soundly rejected....
Thank you!
Given the tables A and B, you are looking for (A U B) - (A & B). In other words, you need A union B minus their intersection. Remember A and B must be union-compatible for this query to work. I would do:
(select * from A
union
select * from B
)
minus
(select * from A
intersect
select * from B
)
May be full outer join?
select coalesce(A.col, B.col)
from A full outer join B on A.col = B.col
where A.col is null or B.col is null;
For computing a set symmetric difference, you can use a combination of MINUS and UNION ALL:
select * from (
(select * from A
minus
select * from B)
union all
(select * from B
minus
select * from A)
)
Your query was rejected because it is syntactically incorrect: the number of columns differ and it confuses cross join and union all. However, I think you have the right idea for solving this.
You can easily fix this:
(select *
from A
union all
select *
from B
) minus
(select *
from A
intersect
select *
from B
);
That is, combine everything using union all and then subtract the rows that occur in both tables.
Of course, if there is a single id, then you can use the id with join and other operations.
Just like Frank Schmitt answered in the meantime:
Here it is including a data example:
WITH
table_a(name) AS (
SELECT 'From_A_1'
UNION ALL SELECT 'From_A_2'
UNION ALL SELECT 'From_A_3'
UNION ALL SELECT 'From_A_4'
UNION ALL SELECT 'From_A_5'
UNION ALL SELECT 'From_BOTH_6'
UNION ALL SELECT 'From_BOTH_7'
UNION ALL SELECT 'From_BOTH_8'
)
,
table_b(name) AS (
SELECT 'From_B_1'
UNION ALL SELECT 'From_B_2'
UNION ALL SELECT 'From_B_3'
UNION ALL SELECT 'From_B_4'
UNION ALL SELECT 'From_B_5'
UNION ALL SELECT 'From_BOTH_6'
UNION ALL SELECT 'From_BOTH_7'
UNION ALL SELECT 'From_BOTH_8'
)
(SELECT * FROM table_a EXCEPT SELECT * FROM table_b)
UNION ALL
(SELECT * FROM table_b EXCEPT SELECT * FROM table_a)
ORDER BY name
;
name
From_A_1
From_A_2
From_A_3
From_A_4
From_A_5
From_B_1
From_B_2
From_B_3
From_B_4
From_B_5
You will need to select all the data from both tables, except where they overlap, and then combine the data with a union. The code provided should work for your example.
SELECT *
FROM
(
SELECT * FROM Table1
EXCEPT SELECT * FROM Table2
)
UNION
SELECT *
FROM
(
SELECT * FROM Table2
EXCEPT SELECT * FROM Table1
)
Hope this helps.

SQL Order of processing

Consider I have a query like
select * from A
Except
select * from B
union all
select * from B
except
select * from A
Query is processed like
select *
from
(
select * from A
Except
select * from B
) a
union all
(
select * from B
Except
select * from A
) b
How is the order of processing defined in sql. Will it process like this at any case
select * from A
Except
select * from
(
select * from B
union all
select * from B
) a
except
select * from A
EXCEPT and UNION are processed "left to right". Meaning that without any parenthesis to make the determination they will process in the order they appear in the sql.
https://msdn.microsoft.com/en-us/library/ms188055.aspx
UNION and EXCEPT have equal precedence but will bind from left to right, meaning they are evaluated in "left to right" order, as they are processed.
From #SeanLange's URL (TL;DR), worth taking note of:
If EXCEPT or INTERSECT is used together with other operators in an
expression, it is evaluated in the context of the following
precedence:
Expressions in parentheses
The INTERSECT operator
EXCEPT and UNION evaluated from left to right based on their position in the
expression

Join two tables with geometry column into one

I have two tables that are exactly the same. I want to join them together into one large dataset. I tried simply SELECT-INTO query but got an error...
SELECT * INTO dbo.ParkingBay
FROM (SELECT * FROM dbo.ParkingBay_Old
UNION
SELECT * FROM dbo.ParkingBay_New) AS PARKING_BAY;
The error is:
The geometry data type cannot be selected as DISTINCT because it is
not comparable.
The UNION performs a DISTINCT on the combined result set.
UNION ALL eliminates this DISTINCT step, but would create the possibility of dupes in the result.
If you are OK with dupe possibility, then try this
SELECT * INTO dbo.ParkingBay
FROM (SELECT * FROM dbo.ParkingBay_Old
UNION ALL
SELECT * FROM dbo.ParkingBay_New) AS PARKING_BAY;
It looks like ALL solves everything:
SELECT * INTO dbo.ParkingBay
FROM (SELECT * FROM dbo.ParkingBay_Old
UNION ALL
SELECT * FROM dbo.ParkingBay_New) AS PARKING_BAY;

SQL Server Query with Derived Table Produces Syntax Error

Hi I have a situaltion similar to this
SELECT *
FROM
(
SELECT *
FROM
Table1
)
I wonder why this gives an error
Incorrect syntax near ')'.
Any help ? Thanks in Advance..
SELECT *
FROM
(
SELECT *
FROM
Table1
) x
You need to give your derived table a name.
Because you need to add an alias. Run it this way:
SELECT * FROM (
SELECT * FROM Table1
) T
Just for the record, MySQL displays the following error given the same situation :)
Every derived table must have its own alias
And you can use the AS keyword to make it more readable
SELECT * FROM ( SELECT * FROM table1 ) as table2