SQL Server - How to display values that differ in two similar tables - sql

I have 2 tables in SQL Server (ver:2008). Both tables have similar structure. Second table has few extra columns. I want to write a query that displays the differences in these tables (for matching fields). Output should display columns from both tables side by side (for comparison).
I tried using EXCEPT which is displaying the results from table 1 that don't match the results in table2. But I need to display both results side-by-side.
Thank you.

You simply need to select the fields you wish to display:
select t1.*, t2.*
from table1 t1
inner join table2 t2 on t1.ID = t2.ID
where t1.field1 <> t2.field1 OR t1.field2 <> t2.field2
OR ...

For example, if you have 2 tables, Products1 and Products2, both with columns Name, Price, Color etc., and you want to list all different products, you can use this:
SELECT Name FROM Products1
UNION
SELECT Name FROM Products2
OR, you can use FULL JOIN keyword, it returns rows when there is a match in one of the tables. For example:
The “Cars” table:
P_Id Name Color Quality City
---- -------- ----- ------- -----------
1 BMW Red good Las Vegas
2 Lexus Blue bad Los Angeles
3 Mercedes Green good MIami
The "Orders" table:
O_Id OrderNo P_Id
---- ------- ----
1 123 3
2 234 3
3 345 1
4 456 1
5 689 18
Now we want to list all the cars and all the people with their orders.
We use:
SELECT Cars.Name, Cars.Color, Orders.OrderNo
FROM Cars
FULL JOIN Orders
ON Cars.P_Id=Orders.P_Id
ORDER BY Cars.Name
The result:
Cars Color OrderNo
-------- ----- -------
BMW Red 345
BMW Red 456
Mercedes Green 123
Mercedes Green 234
Lexus Blue -
- - 689

Give this a shot. It assumes that there's one column (a) that is identical between the tables, and the rest (b, c, ...) are potentially different.
SELECT t1.a, t2.a, t1.b, t2.b, t1.c, t2.c, ...
FROM table1 t1
JOIN table2 t2
ON t1.a = t2.a
AND NOT (t1.b = t2.b AND t1.c = t2.c ...)

SELECT * FROM
(
SELECT * FROM TABLE1
EXCEPT
SELECT * FROM TABLE2
) T1
UNION ALL
SELECT * FROM
(
SELECT * FROM TABLE2
EXCEPT
SELECT * FROM TABLE1
) T2

Related

Join two tables with switch case in order to avoid one to many join

I have two tables, t1 and t2.
Table t1:
Name address id
---- ------- --
rob 32 cgr 12
mary 31 lmo 42
tom axel St 2
Table t2:
ID Flag expense
-- ---- --------
12 Shop 1200
12 Educ 14000
42 educ 4000
Now I will have to create a table which will have attributes from t1 plus two more attributes that is expense in shop and expense in educ
Table t3
Name address id Shop_ex Educ_ex
---- ------- -- ------- -------
rob 32 cgr 12 1200 14000
mary 31 lmo 42 NULL 4000
tom axel st 2 NULL NULL
How to accomplish this?
I tried doing a left join t2 with switch case but it gives me multiple record as the join is becoming one to many.
select
t1.name, t1.address, t1.id,
case
when t2.flag = "shop" then t2.expense
else null
end as shop_ex
case
when t2.flag = "educ" then t2.expense
else null
end as educ_ex
from
t1
left join
t2 on (t1.id = t2.id)
It seems I will have to convert t2 table first before joining, to have a single record on the basis of flag. But I am not sure how to do that.
Please mind the tables are huge and optimized query will be nice.
Please suggest.
You only need to join the first table to the second one, twice:
SELECT t1.Name, t1.address, t1.id, t2a.expense AS Shop_ex, t2b.expense AS Educ_ex
FROM table1 t1
LEFT JOIN table2 t2a
ON t2a.ID = t1.id AND t2a.Flag = 'Shop'
LEFT JOIN table2 t2b
ON t2b.ID = t1.id AND t2b.Flag = 'Educ'
Demo

Finding IDs in one table not in another

I have two tables:
table1
ID | Name | Code
1 Joe 123
2 Sam 674
3 Mike 321
table2
ID | User Name| Code
1 Joe 123
2 Sam 674
3 Mike 321
4 John 457
5 Tim 235
Desired result:
4|John|457
5| Tim|235
Tabe1 and table2 code is identical. Table 1 code is a new field added thus contains no data for any record. Using the IDs as keys I took the codes from table2 and populated them in table1. However table1 has considerably less IDs then table2 so table2 has more codes then table1. I want to query which codes did not get transferred to table1. I thought it would be as simple as:
select *
from table2 t2
where t2.Code is not null and
t2.Code not in (select t1.Code from table1 t1 where t1.Code is not null);
This returns nothing which is strange to me. What do I need to adjust in this query? This is for oracle.
You might try the following:
SELECT t2.*
FROM table2 t2
WHERE NOT EXISTS ( SELECT 1 FROM table1 t1
WHERE t1.code = t2.code );

fusion 2 tables with inner join

in my database i have 2 tables.
table1
i have ID and NAMES
table2
i have ID, IDASSOCIATION, QUANTITY
so
i have 2 names in table1:
john and tom
and in table2 i have 3 lignes
john, 1
tom, 1
john, 1
nombre one is the quantity
in my result i want get
john = 2
and tom = 1
so i do this:
sql = "SELECT t1.*, t2.IDASSOCIATION, (SELECT SUM(t2.id_qte) FROM associationdepotarticle t2 WHERE t1.fusiontable = t2.fusiontable GROUP BY t2.IDASSOCIATION) as id_qte FROM articletable t1, associationdepotarticle t2";
but i not get this:
john = 2
tom = 1
why ? what i will do, i need correction please
You can just join the tables together and use sum:
select t1.name, sum(t2.quantity)
from table1 t1
join table2 t2 on t1.id = t2.idassociation
group by t1.name
It's not completely clear from your sample data what to join on, but I assume it's the idassociation field. If you want to return those names in table1 which aren't in table2, then use an outer join.

Select single row from two table related using mapping table SQL Server

I have three tables: Table1, Table2, Table1Table2Mapping.
Each tabel1 data having multiple data in tabel1, this table1 relation table2 is done through the mapping table the Primary key of the table1 and table2 is put in mapping table.
Table1:
Table1_ID Name ,Other columns
--------- ---- ------
1 Name1
2 Name2
3 Name3
Table2:
Table2_ID Title
--------- -----
101 Title1
102 Title2
103 Title3
104 Title4
105 Title5
Table1Table2Mapping:
Table1_ID Table2_ID
--------- ------------
1 101
1 102
2 103
3 104
3 105
I am getting all the related rows from table1 and its relation in table1 through mappping table
I need to select single row for each Table1 row.
Like this
Table1_ID Name Title
--------- ------- -----
1 Name1 Title1
2 Name2 Title3
3 Name3 Title4
The CROSS APPLY will do the trick:
SELECT
T1.Table1_ID
, T1.Name
, TMP.Title
FROM
Table1 T1
CROSS APPLY (
SELECT TOP(1)
T2.Title
FROM
Table2 T2
INNER JOIN Table1Table2Mapping TTM
ON T2.Table2_ID = TTM.Table2_ID
WHERE
TTM.Table1_ID = T1.Table1_ID
ORDER BY
TTM.TAble2_ID ASC -- You can change this order to what you want
) TMP
You can change the order of the subquery.
SQL Fiddle
Using CROSS APPLY in TechNet
EDIT
IF it is enough, you can use aggregation too:
SELECT
T1.Table1_ID
, T1.Name
, MIN(T2.Title) -- You can use MAX
FROM
Table1 T1
INNER JOIN Table1Table2Mapping TTM
ON TTM.Table1_ID = T1.Table1_ID
INNER JOIN Table2 T2
ON T2.Table2_ID = TTM.Table2_ID
GROUP BY
T1.Table1_ID
, T1.Name
(This gives the same result for the provided dataset, but in real life, the result of this and the previous solution mostly different!
use outer apply in sql server 2005 and later
Select Table1.*, ttt.Title From Table1 Outer Apply
(Select Top 1 Table2.* From Table2 Inner Join Table1Table2Mapping
On Table2.Table2_Id = Table1Table2Mapping.Table2_Id
Where Table1.Table1_Id = Table1Table2Mapping.Table1_Id) ttt

postgreSQL Duplicate rows counting on join

I have one complicated question. I'll try to explain it with example:
have one table that have primary key, and I want to join other table there the first's table primary key is foreign key, and I want If in the second table there is duplicate foreign key to select the number of repeatability. For example:
1-st table:
id name
--- -----
1 Greg
2 Alan
3 George
4 John
5 Peter
2-nd table
id aid data
--- ----- -------
1 2 CCCV
2 2 VVVV
3 3 DDDDD
4 3 SSSS
5 4 PPPPP
I want the result of the join to be:
id(1st table) aid name Data Number
----------- ---- ----- ----- -----
1 null Greg null 1
2 1 Alan CCCV 1
2 2 Alan VVVV 2
3 3 George DDDDD 1
3 4 George SSSS 2
4 5 John PPPPP 1
5 null Peter null 1
I searched a lot, I couldn't find anything. Maybe I do not know how search, or there is no such thing as what I want to do.
SELECT Table1.id, Table2.id as aid, Table1.name, Table2.data,
GREATEST(1, (SELECT COUNT(*)
FROM Table2 t2
WHERE t2.aid = Table1.id
AND t2.id <= Table2.id))
AS number
FROM Table1
LEFT JOIN Table2
ON Table2.aid = Table1.id
ORDER BY id, aid;
works in both MySQL and PostgreSQL.
As per my comment, you've tagged this both MySQL and PostgreSQL.
This answer is for PostgreSQL.
SELECT
table1.id,
table2.aid,
table1.name,
table2.data,
ROW_NUMBER() OVER (PARTITION BY table1.id ORDER BY table2.aid) AS number
FROM
table1
LEFT JOIN
table2
ON table1.id = table2.aid
Queries for PostgreSQL 8.3 which has no window functions.
With bigger tables it is regularly much faster to use a JOIN instead of a correlated sub-query.
The first query aggregates values for Table2 before joining to Table1, which should befaster, too:
SELECT t1.id, t2.aid, t1.name, t2.data, COALESCE(t2.ct, 1) AS number
FROM Table1 t1
LEFT JOIN (
SELECT x.aid, x.data, count(y.aid) + 1 AS ct
FROM Table2 x
LEFT JOIN Table2 y ON x.aid = y.aid AND x.id > y.id
GROUP BY x.aid, x.data
) t2 ON t2.aid = t1.id
ORDER BY t1.id, t2.ct;
And ORDER BY should be fixed.
Alternative without sub-query. Might be faster, yet:
SELECT t1.id, t2.aid, t1.name, t2.data, count(*) + count(t3.id) AS number
FROM Table1 t1
LEFT JOIN Table2 t2 ON t2.aid = t1.id
LEFT JOIN Table2 t3 ON t3.aid = t2.aid AND t3.id < t2.id
GROUP BY t1.id, t2.aid, t1.name, t2.data
ORDER BY t1.id, count(t3.id);
Not sure, didn't test with a bigger set. Test performance with EXPLAIN ANALYZE. Could you report back your results?