Mssql union two tables based on column value - sql

I have to tabels (tab_a and tab_b) both carrying customers data. The two tables have some records in common, or better, customers in common. The problem is they are identified by different customer's code and the names of the same customer may vary from one table to the other. The only common key they have is the VAT number.
What i need is a recordset with the customers from both tables but without dupicates.
I tried a regular UNION but the problem is that if the name of the customers is written slightly different from one tabel to the other i get a duplicate.
I short I need the result of
SELECT t1.vatnumber FROM tab_a AS t1 UNION t2.vatnumber FROM tab_b AS t2
But with the adition of the name of the cusotmers and his custumer code (taken from tab_a or if not present in tab_a from tab_b)
Any help is truly appreciated.
Regards

You are not going to get what you want readily with distinct. A better approach might be union all with aggregation. The following returns what you want -- but without precedence. That is, if a name or code exists in both tables, then an arbitrary one is returned:
select vatnumber, max(name) as name, max(code) as code
from ((select a.vatnumber, a.name, a.code
from tab_a
) union all
(select b.vatnumber, b.name, b.code
from tab_b
)
) ab
group by vatnumber;
If you want precedence, then it is a bit more cumbersome. Here is one method:
select vatnumber,
coalesce(max(case when which = 'a' then name end), max(name)) as name,
coalesce(max(case when which = 'a' then code end), max(code)) as code
from ((select a.vatnumber, a.name, a.code, 'a' as which
from tab_a
) union all
(select b.vatnumber, b.name, b.code, 'b' as which
from tab_b
)
) ab
group by vatnumber;

Don't use UNION, it is simpler with FULL OUTER JOIN:
SELECT
ISNULL(a.vatnumber, b.vatnumber) vatnumber,
ISNULL(a.name, b.name) name,
...
FROM tab_a a FULL JOIN tab_b b ON a.vatnumber = b.vatnumber
Syntax will depend on DB that you are using. e.g. This example should be ok for MSSQL.

Related

SQL join to join 2 tables having common columns without using join keyword

t2I'm trying to join 2 tables without using join keyword.Both tables have same kind of data but order is different. I want to display Rank,Airport info from both tables namely airports2017 and airports2010 when their ranks are different in 2 tables otherwise skip that row. How can i do this without using join keyword?
t1
I really am not certain if this is what you are looking for, but this will find an list the differences in two tables that have columns col_a and col_b:
WITH
aset AS
(SELECT col_a, col_b FROM table_a
MINUS
SELECT col_a, col_b FROM table_b),
bset AS
(SELECT col_a, col_b FROM table_b
MINUS
SELECT col_a, col_b FROM table_a)
SELECT 'A unique records' AS TYPE, a.*
FROM aset a
UNION ALL
SELECT 'B unique records' AS TYPE, a.*
FROM bset a
While I am not sure why you want to do this, this query will give you what you want:
select airport, max(rank2017) as Rank2017, max(Rank2018) as Rank2018 from
(
select airport, airportrank as rank2017, 0 as rank2018 from airport2017
union
select airport, 0 as rank2017, airportrank as rank2018 from airport2018
) tabs
group by airport
If you only want ones where the rank has changed, add at the bottom:
having max(rank2017)<>max(Rank2018)
this will work as you wanted withuot using join:
select a.rank,a.airport from t1 a, t2 b
where a.rank=b.rank
thank you.

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)

PostgreSQL union two tables and join with a third table

I want to union to tables and join them with a third metadata table and I would like to know which approach is the best/fastest?
The database is a PostgreSQL.
Below is my two suggestions, but other approaches are welcome.
To do the join before the union on both tables:
SELECT a.id, a.feature_type, b.datetime, b.file_path
FROM table1 a, metadata b WHERE a.metadata_id = b.id
UNION ALL
SELECT a.id, a.feature_type, b.datetime, b.file_path
FROM table2 a, metadata b WHERE a.metadata_id = b.id
Or to do the union first and then do the join:
SELECT a.id, a.feature_type, b.datetime, b.file_path
FROM
(
SELECT id, feature_type, metadata_id FROM table1
UNION ALL
SELECT id, feature_type, metadata_id FROM table2
)a, metadata b
WHERE a.metadata_id = b.id
Run an EXPLAIN ANALYZE on both statements then you will see which one is more efficient.
it can be unpredictable due to sql-engine optimizator. it's better to look at the execution plan. finally both approaches can be represented in the same way
In so far as I can remember, running Explain will reveal that PostgreSQL interprets the second as the first provided that there is no group by clause (explicit, or implicit due to union instead of union all) in any of the subqueries.

SQL getting results from two tables in order by primary key

In my query I want to get the rows from two different tables descending by their primary keys. They have two different keys so is it possible to be able to do this in one query?
Your question is a little vague. To "get rows from two different tables" you can do a JOIN, or you can do a UNION.
In the case of a JOIN:
SELECT a.id, a.something, b.id, b.something
FROM a
INNER JOIN b ON b.aId = a.id
ORDER BY a.id, b.id
In the case of a UNION:
SELECT id, something
FROM (
SELECT a.id. a.something FROM a
UNION
SELECT b.id, b.something FROM b
) t
ORDER BY t.id
These are very different, but it seems like one of them will meet your needs.
(Note that UNION by default eliminates duplicates. Use UNION ALL to keep duplicates.)
SELECT *
FROM ( select a.pk, a.foo, a.bar from a
union
select b.pk, b.foo, b.bar from b
) c
ORDER BY c.pk DESC;

How do I merge data from two tables in a single database call into the same columns?

If I run the two statements in batch will they return one table to two to my sqlcommand object with the data merged. What I am trying to do is optimize a search by searching twice, the first time on one set of data and then a second on another. They have the same fields and I’d like to have all the records from both tables show and be added to each other. I need this so that I can sort the data between both sets of data but short of writing a stored procedure I can’t think of a way of doing this.
Eg. Table 1 has columns A and B, Table 2 has these same columns but different data source. I then wan to merge them so that if a only exists in one column it is added to the result set and if both exist it eh tables the column B will be summed between the two.
Please note that this is not the same as a full outer join operation as that does not merge the data.
[EDIT]
Here's what the code looks like:
Select * From
(Select ID,COUNT(*) AS Count From [Table1]) as T1
full outer join
(Select ID,COUNT(*) AS Count From [Table2]) as T2
on t1.ID = T2.ID
Perhaps you're looking for UNION?
IE:
SELECT A, B FROM Table1
UNION
SELECT A, B FROM Table2
Possibly:
select table1.a, table1.b
from table1
where table1.a not in (select a from table2)
union all
select table1.a, table1.b+table2.b as b
from table1
inner join table2 on table1.a = table2.a
edit: perhaps you would benefit from unioning the tables before counting. e.g.
select id, count() as count from
(select id from table1
union all
select id from table2)
I'm not sure if I understand completely but you seem to be asking about a UNION
SELECT A,B
FROM tableX
UNION ALL
SELECT A,B
FROM tableY
To do it, you would go:
SELECT * INTO TABLE3 FROM TABLE1
UNION
SELECT * FROM TABLE2
Provided both tables have the same columns
I think what you are looking for is this, but I am not sure I am understanding your language correctly.
select id, sum(count) as count
from (
select id, count() as count
from table1
union all
select id, count() as count
from table2
) a
group by id