SQL UNION - Adding Source - sql

I am currently using UNION on two queries (see psuedo-code below):
query1
UNION
query2
I want to add an additional column to my results that says the source of the data. The new column called "Source" would return one of the following: "1", "2", or "both".
Being able to handle "both" is very important because query1 and query2 will have similar results and many overlapping records. If anyone could help point me in the right direction, especially with how to handle the "both" case, that would be greatly appreciated!
Sample:
If query1 has a row "Apple,Yellow,Bob" and query2 has the same row, then the result I'm hoping for is:
"Apple,Yellow,Bob,Both"
The individual queries themselves will not have duplicates, but there may be the same row both in query1 and query2 (as seen above).

you can make use of an additional column col4 like this
select col1,col2,col3,sum(col4)
from(
Select col1, col2, col3, 1 as col4 from table1
UNION
Select col1,col2,col3, 2 as col4 from table4
)
group by col1,col2,col3
The records with col4=1 only exist in table1.
The records with col4=2 only exist in table2.
The records with col4=3 exist in both table1+table

add a Source field to both query 1 and query 2:
select 1 as source, ...
from table1
union
select 2 as source, ...
from table2

Here's one way
WITH T
AS (SELECT '1' AS Source,
Col1,
Col2,
Col3
FROM table1
UNION ALL
SELECT '2' AS Source,
Col1,
Col2,
Col3
FROM table2)
SELECT CASE
WHEN MAX(Source) = MIN(Source) THEN Source
ELSE 'Both'
END AS Source,
Col1,
Col2,
Col3
FROM T
GROUP BY Col1,
Col2,
Col3

One more approach
SELECT col1
,col2
,source = CASE
WHEN count(DISTINCT source) > 1
THEN 'Both'
ELSE max(source)
END
FROM (
SELECT col1 ,col2, source = 'source1'
FROM source1
UNION ALL
SELECT col1, col2, source = 'source2'
FROM source2
) u
GROUP BY col1, col2

You can try this
SELECT
a.col1 , a.col2,
CASE WHEN MAX(a.Source) <> MIN(a.Source)
THEN 'BOTH'
ELSE MAX(a.Source) END
FROM
(
SELECT
col1, col2 ,'Source2' AS Source
FROM Table1
UNION ALL
SELECT
col1, col2 ,'Source1' AS Source
FROM Table2
) a
GROUP BY
a.col1 , a.col2
Link to the Sample

Related

Oracle SQL Unions error "query block has incorrect number of results columns"

I'm trying to write a query that pulls data from a lot of tables, and has about 20 unions. It's pulling the same information repeatedly, but with more layers each time, to show a sort of tree.
I want to compare the final two columns. I'm using a case to do this, and if I add a case to this query then I get the error "query block has incorrect number of results columns". This seems to be because the final select in the union has an extra column (the compare case).
Is there any way to work around this? I don't want to add the case to each select, as this would add about 15 more columns that I don't want.
Use a sub-query:
SELECT col1,
col2,
CASE
WHEN col1 = 'somevalue'
THEN 'someresult'
ELSE 'otherresult'
END AS col3
FROM (
SELECT col1, col2 FROM table1 UNION ALL
SELECT col1, col2 FROM table2 UNION ALL
SELECT col1, col2 FROM table3
-- ...
);
Or use a sub-query factoring clause:
WITH data ( col1, col2 ) AS (
SELECT col1, col2 FROM table1 UNION ALL
SELECT col1, col2 FROM table2 UNION ALL
SELECT col1, col2 FROM table3
-- ...
)
SELECT col1,
col2,
CASE
WHEN col1 = 'somevalue'
THEN 'someresult'
ELSE 'otherresult'
END AS col3
FROM data;

Concatenate tables (UNION ALL) where one of the tables lacks one of the columns

I am trying to combine three tables in an SQLite database into one new combined table. The three tables have the same column names, but the third table is missing one of the columns. Here is how I am trying to do it:
CREATE TABLE cobmined
AS
SELECT col1, col2, col3
FROM
(
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2 from table3
) s
;
This works when doing this only on the first two tables, when adding the third table I get the message:
SELECTs to the left and right of UNION do not have the same number of result columns
Is there a way to let SQL ignore the missing column and leave it with NULLs if needed?
Add a NULL value to the third table
CREATE TABLE cobmined
AS
SELECT col1, col2, col3
FROM
(
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2, null from table3
) s
;
Also, no need for sub-query
CREATE TABLE cobmined
AS
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2, null from table3
I want to note that you don't need the subquery:
CREATE TABLE combined AS
SELECT col1, col2, col3 from table1
UNION ALL
SELECT col1, col2, col3 from table2
UNION ALL
SELECT col1, col2, NULL from table3;
In addition, you may find that a view is more suitable for your purposes than an actual table.

How do I combine multiple tables into one new table? All of the columns headers are the same and in the same order

I have 12 tables in SQL Server with the exact same columns that I would like to combine into one brand new table. I don't want any data/rows deleted.
Thanks
Use union all:
insert into NewTable(col1, col2)
select col1, col2
from(
select col1, col2 from Table1
union all
select col1, col2 from Table2
union all
select col1, col2 from Table3
.....
)t
You can create new table while selecting like:
select col1, col2
into NewTable
from(
select col1, col2 from Table1
union all
select col1, col2 from Table2
union all
select col1, col2 from Table3
.....
)t

SQL Where Not Exists

I think I have a misunderstanding of how NOT EXISTS work and hope it can be clarified to me.
Here is the sample code I am running (also on SQL Fiddle)
select sum(col1) col1, sum(col2) col1, sum(col3) col3
from (
select 1 col1, 1 col2, 1 col3
from dual tbl1
)
where not exists(
select 2 col1, 1 col2, 1 col3
from dual tbl2
)
I thought that it should return:
1, 1, 1
But instead it returns nothing.
I make this assumption only on the fact that I though NOT EXISTS would give me a list of all the rows in the first query that do not exist in the second query (in this case 1,1,1)
Why does this not work
What would be the appropriate way to make it work the way I am expecting it to?
You are performing an uncorrelated subquery in your NOT EXISTS() condition. It always returns exactly one row, therefore the NOT EXISTS condition is never satisfied, and your query returns zero rows.
Oracle has a rowset difference operator, MINUS, that should do what you wanted:
select sum(col1) col1, sum(col2) col1, sum(col3) col3
from (
select 1 col1, 1 col2, 1 col3
from dual tbl1
MINUS
select 2 col1, 1 col2, 1 col3
from dual tbl2
)
SQL Server has an EXCEPT operator that does the same thing as Oracle's MINUS. Some other databases implement one or the other of these.
EXISTS just returns true if a record exists in the result set; it does not do any value checking. Since the sub-query returns one record, EXISTS is true, NOT EXISTS is false, and you get no records in your result.
Typically you have a WHERE cluase in the sub-query to compare values to the outer query.
One way to accomplish what you want is to use EXCEPT:
select sum(col1) col1, sum(col2) col1, sum(col3) col3
from (
select 1 col1, 1 col2, 1 col3
from dual tbl1
)
EXCEPT(
select 2 col1, 1 col2, 1 col3
from dual tbl2
)
A not exists that includes a select from dual will never return anything. Not exists will exclude rows where the embedded SQL returns something. Normally not exists should be used more like this:
select ... from MY_TABLE A where not exists (select 1 from OTHER_TABLE B where A.SOME_COL = B.SOME_COL)
As using NOT EXISTS is not good approach as it is return only single row so try it with MINUS or EXCEPT
select sum(col1) col1, sum(col2) col1, sum(col3) col3 from ( select 1 col1, 1 col2, 1 col3 from dual tbl1 MINUS select 2 col1, 1 col2, 1 col3 from dual tbl2 )
select sum(col1) col1, sum(col2) col1, sum(col3) col3 from ( select 1 col1, 1 col2, 1 col3 from dual tbl1 ) EXCEPT( select 2 col1, 1 col2, 1 col3 from dual tbl2 )

select all columns with one column has different value

In my table,some records have all column values are the same, except one. I need write a query to get those records. what's the best way to do it? the table is like this:
colA colB colC
a b c
a b d
a b e
What's the best way to get all records with all the columns? Thanks for everyone's help.
Assuming you know that column3 will always be different, to get the rows that have more than one value:
SELECT Col1, Col2
FROM Table t
GROUP BY Col1, Col2
HAVING COUNT(distinct col3) > 1
If you need all the values in the three columns, then you can join this back to the original table:
SELECT t.*
FROM table t join
(SELECT Col1, Col2
FROM Table t
GROUP BY Col1, Col2
HAVING COUNT(distinct col3) > 1
) cols
on t.col1 = cols.col1 and t.col2 = cols.col2
Just select those rows that have the different values:
SELECT col1, col2
FROM myTable
WHERE colWanted != knownValue
If this is not what you are looking for, please post examples of the data in the table and the wanted output.
How about something like
SELECT Col1, Col2
FROM Table
GROUP BY Col1, Col2
HAVING COUNT(*) = 1
This will give you Col1, Col2 that have unique data.
Assuming col3 has the difs
SELECT Col1, Col2
FROM Table
GROUP BY Col1, Col2
HAVING COUNT(*) > 1
OR TO SHOW ALL 3 COLS
SELECT Col1, Col2, Col3
FROM Table1
GROUP BY Col1, Col2, Col3
HAVING COUNT(Col3) > 1