SQL Server Query to find different names in two tables - sql

I have a situation here.
I have two tables:
I need a sql query which will print the Col names which are different in two tables.
For example, in this case the query should print the result as:
The reason is clear that m is present in Table-1 but not present in Table-2. Similar is the case with z which is in Table-2 but not in Table-1.
I am really stcuk here, please help.
The colum names are not case-sensitive.
Thanks.

You could also use NOT EXISTS to get the result:
select col1
from table1 t1
where not exists (select 1
from table2 t2
where t1.col1 = t2.col1)
union all
select col1
from table2 t2
where not exists (select 1
from table1 t1
where t1.col1 = t2.col1);
See SQL Fiddle with Demo
Or even NOT IN:
select col1
from table1 t1
where col1 not in (select col1
from table2 t2)
union all
select col1
from table2 t2
where col1 not in (select col1
from table1 t1);
See SQL Fiddle with Demo

Try:
select coalesce(t1.Col1, t2.Col1)
from [Table-1] t1
full outer join [Table-2] t2 on t1.Col1 = t2.Col1
where t1.Col1 is null or t2.Col1 is null
SQLFiddle here.
Alternatively:
select Col1 from
(select Col1 from [Table-1] union all select Col1 from [Table-2]) sq
group by Col1 having count(*) = 1
SQLFiddle here.

I Think simplest one is this
SELECT COL1 AS ResultCol FROM TABLE1 where COL1 not in (select COL2 from TABLE2) UNION SELECT COL2 AS ResultCol FROM TABLE2 where COL2 not in (select COL1 from table1)

declare #tab1 table(id int,col1 varchar(1))
declare #tab2 table(id int,col1 varchar(1))
INSERT INTO #tab1
([id], [Col1])
VALUES
(1, 'A'),
(2, 'B'),
(3, 'm'),
(4, 'c')
INSERT INTO #tab2
([id], [Col1])
VALUES
(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'z')
select b.id,b.col1 from
(
select a.id,a.col1,b.col1 x from #tab1 a left join #tab2 b on a.col1 = b.col1
union
select b.id,b.col1,a.col1 x from #tab1 a right join #tab2 b on a.col1 = b.col1
) b
where b.x is null

There's a feature specifically for this operation. EXCEPT and INTERCEPT.
Find which values (single column result or multi-column result) are not present in the following queries
--What's in table A that isn't in table B
SELECT col1 FROM TableA
EXCEPT
SELECT col1 FROM TableB
--What's in table B that isn't in table A
SELECT col1 FROM TableB
EXCEPT
SELECT col1 FROM TableA
Likewise, the INTERCEPT keyword tells you what is shared
--What's in table A and table B
SELECT col1 FROM TableA
INTERCEPT
SELECT col1 FROM TableB

You can also use FULL OUTER JOIN operator.
Visual Representation of SQL Joins
SELECT ROW_NUMBER() OVER(ORDER BY COALESCE(t1.Col1, t2.Col1)) AS id,
COALESCE(t1.Col1, t2.Col1) AS ResultCol
FROM Table1 t1 FULL JOIN Table2 t2 ON t1.Col1 = t2.Col1
WHERE t1.Col1 IS NULL OR t2.Col1 IS NULL
See example on SQLFiddle

Related

inserting into a table records from another table with a condition

Let's say I have two tables t1 and t2.
t1 has two integer cols col1 (primary) and col2
t2 has two cols a foreign key of t1.col1 and t2.col2
I want to do the following
Retrieve only the records where t1.col2 is unique OR if t1.col2 is duplicate only those if t2.col2 is not null.
Insert the above records into another summary table, let's say t3
This is what I tried:
insert into t3 (col1,col2)
select col1, col2
from t1
where t.col1 in (select A.col1 from t1 as A
group by 1
having count(*) > 1
union
select col1, col2
from t1, t2
where t.col1 in (select A.col1 from t1 as A
group by 1
having count(*) > 1
and t2.col2 is not null;
While the 'union qry' works on its own, the insert is not happening.
Any ideas or any other efficient way to achieve this please
You can select the records you want using:
select t1.*
from (select t1.*, count(*) over (partition by col2) as cnt
from t1
) t1
where cnt = 1 or
exists (select 1 from t2.col1 = t1.col1 and t2.col2 is null);
The rest is just an insert.

Find unmatched rows between two tables

Given this setup:
CREATE TABLE table1 (column1 text, column2 text);
CREATE TABLE table2 (column1 text, column2 text);
INSERT INTO table1 VALUES
('A', 'A')
, ('B', 'N')
, ('C', 'C')
, ('B', 'A');
INSERT INTO table2 VALUES
('A', 'A')
, ('B', 'N')
, ('C', 'X')
, ('B', 'Y');
How can I find missing combinations of (column1, column2) between these two tables? Rows not matched in the other table.
The desired result for the given example would be:
C | C
B | A
C | X
B | Y
There can be duplicate entries so we'd want to omit those.
One method is union all:
select t1.col1, t1.col2
from t1
where (t1.col1, t1.col2) not in (select t2.col1, t2.col2 from t2)
union all
select t2.col1, t2.col2
from t2
where (t2.col1, t2.col2) not in (select t1.col1, t1.col2 from t1);
If there are duplicates within a table, you can remove them by using select distinct. There is no danger of duplicates between the tables.
Seems to be a perfect task for set operations:
( --all rows from table 1 missing in table 2
select *
from table1
except
select *
from table2
)
union all -- both select return distinct rows
( -- all rows in table 2 missing in table 1
select *
from table2
except
select *
from table1
)
You can try to use not exists with a subquery, then use UNION ALL
select Column1,Column2 from table1 t1
where NOT exists
(
select 1
FROM table2 t2
where t1.Column1 = t2.Column1 or t1.Column2 = t2.Column2
)
UNION ALL
select Column1,Column2 from table2 t1
where NOT exists
(
select 1
FROM table1 t2
where t1.Column1 = t2.Column1 or t1.Column2 = t2.Column2
)
You can try set operations. EXCEPT to find the rows in table but not in the other and UNION to put the partial results into one.
(SELECT column1,
column2
FROM table1
EXCEPT
SELECT column1,
column2
FROM table2)
UNION
(SELECT column1,
column2
FROM table2
EXCEPT
SELECT column1,
column2
FROM table1);
If you don't need duplicate elimination you can try to use the ALL variants (EXCEPT ALL and UNION ALL). They are generally faster, as the DBMS doesn't have to look for and eliminate duplicates.
The devil is in the details with this seemingly simple task.
Short and among the fastest:
SELECT col1, col2
FROM (SELECT col1, col2, TRUE AS x1 FROM t1) t1
FULL JOIN (SELECT col1, col2, TRUE AS x2 FROM t2) t2 USING (col1, col2)
WHERE (x1 AND x2) IS NULL;
The FULL [OUTER] JOIN includes all rows from both sides, but fills in NULL values for columns of missing rows. The WHERE conditions (x1 AND x2) IS NULL identifies these unmatched rows. Equivalent: WHERE x1 IS NULL OR x2 IS NULL.
To eliminate duplicate pairs, add DISTINCT (or GROUP BY) at the end - cheaper for few dupes:
SELECT DISTINCT col1, col2
FROM ...
If you have many dupes on either side, it's cheaper to fold before the join:
SELECT col1, col2
FROM (SELECT DISTINCT col1, col2, TRUE AS x1 FROM t1) t1
FULL JOIN (SELECT DISTINCT col1, col2, TRUE AS x2 FROM t2) t2 USING (col1, col2)
WHERE (x1 AND x2) IS NULL;
It's more complicated if there can be NULL values. DISTINCT / DISTINCT ON or GROUP BY treat them as equal (so dupes with NULL values are folded in the subqueries above). But JOIN or WHERE conditions must evaluate to TRUE for rows to pass. NULL values are not considered equal in this, the FULL [OUTER] JOIN never finds a match for pairs containing NULL. This may or may not be desirable. You just have to be aware of the difference and define your requirements.
Consider the added demo in the SQL Fiddle
If there are no NULL values, no duplicates, but an additional column defined NOT NULL in each table, like the primary key, let's name each id, then it can be as simple as:
SELECT col1, col2
FROM t1
FULL JOIN t2 USING (col1, col2)
WHERE t1.id IS NULL OR t2.id IS NULL;
Related:
Select rows which are not present in other table
PostgreSQL - Create table as select with distinct on specific columns

How to get the following join query

How to get the following join
input:
table1: table2:
col1 Col1 col2 col3
A A 1 2
B B 4 5
C
output:
col1 col2 col3
A 1 2
B 4 5
c - -
SELECT t1.col1, t2.col2, t2.col3
FROM table1 t1
LEFT JOIN table2 t2 ON t1.col1=t2.col1
;
You can do this using full outer join:
select coalesce(t1.col1, t2.col1), t2.col2, t2.col3
from table1 t1 full outer join
table2 t2
on t1.col1 = t2.col1;
This returns all rows from both tables, even those that don't match (it is a left and right outer join at the same time).
You can also do this using union all and aggregation:
select col1, max(col2) as col2, max(col3) as col3
from ((select col1, NULL as col2, NULL as col3
from table1
) union all
(select col1, col2, col3
from table2
)
) t
group by col1;
select t1.col1, t2.col2, t2.col3
from table1 t1
left outer join table2 t2
on t1.col1 = t2.col1
Maybe something like this if you wan't the '-'
SELECT t1.col1, coalesce(t2.col2,'-') as col2, coalesce(t2.col3,'-') as col3
FROM table1 t1
LEFT JOIN table2 t2 ON t1.col1=t2.col1
See my sqlfiddle
create table table1(
col1 char(1)
);
insert into table1 values('A');
insert into table1 values('B');
insert into table1 values('C');
create table table2(
col1 char(1),
col2 int,
col3 int
);
insert into table2 values('A',1,2);
insert into table2 values('B',4,5);
select
t1.col1,
coalesce(t2.col2,'-'),
coalesce(t2.col3,'-')
from
table1 t1
left join table2 t2 on t1.col1=t2.col1
;
http://sqlfiddle.com/#!2/bc768/2
You need to do an outer join
SELECT *
FROM table1 t1,
table2 t2
WHERE t1.col1 = t2.col1(+)

Using the names of columns stored within fields to retrieve data from a different table

I was wondering if there exists code to accomplish the following in SQL-Server 2008?
Table 1:
id column name
-------------------
1 col1
2 col2
3 col3
4 col2
Table 2:
col1 col2 col3
--------------------
a b c
Result Table:
id data
--------------------
1 a
2 b
3 c
4 b
Thanks in advance, I really have no idea how to do this.
You can use UNPIVOT table2 to access the data from the columns:
select t1.id, t2.value
from table1 t1
left join
(
select value, col
from table2
unpivot
(
value
for col in (col1, col2, col3)
) u
) t2
on t1.name = t2.col
see SQL Fiddle with Demo
Or you can use a UNION ALL to access the data in table2:
select t1.id, t2.value
from table1 t1
left join
(
select col1 value, 'col1' col
from table2
union all
select col2 value, 'col2' col
from table2
union all
select col3 value, 'col3' col
from table2
) t2
on t1.name = t2.col
see SQL Fiddle with Demo
I dont see how you do it withou a column connection them:
Table1:
ID
ColumnName
Table2:
Table1ID
Letter
Select table1.id, table2.Letter
from table1
inner join table2 on table1.ID = table2.Table1ID
You can do this with a case statement and cross join:
select t1.id,
(case when t1.columnname = 'col1' then t2.col1
when t1.columnname = 'col2' then t2.col2
when t1.columnname = 'col3' then t2.col3
end) as data
from table1 t1 cross join
table2 t2

SQL Server self join

I have a table as below:
table1
col1 col2 col3
1 A 1
2 B 1
3 A 2
4 D 2
5 X 3
6 G 3
Now can I get the result like below from above table. THe col2 in the below resultset is based on the col3 in table1 above. In above table1 col2, A and B have same id value in COL3 (i.e 1) so in the result set we just separate it in new columns and so on. A and D have same id COL3 (i.e 2) and X and G have same id in COL3 (i.e 3) in above table1. ANyone can write a sql query to get the following result.
col1 col2
A B
A D
X G
SELECT
col1 = t.col2,
col2 = t2.col2
FROM table1 t
INNER JOIN table1 t2 ON t.col3 = t2.col3 AND t.col1 < t2.col1
SELECT
t1.col2 as col1,
t2.col2
FROM Table1 t1
INNER JOIN Table1 t2 on t1.col3 = t2.col3
WHERE t1.col1 > t2.col1
If you are on SQL Server 2005 or later:
WITH ranked AS (
SELECT
*,
rn = ROW_NUMBER() OVER (PARTITION BY col3 ORDER BY col2)
FROM table1
)
SELECT
col1 = r1.col2,
col2 = r2.col2
FROM ranked r1
INNER JOIN ranked r2 ON r1.col3 = r2.col3
WHERE r1.rn = 1
AND r2.rn = 2
select
a.col2 as "col1",
b.col2 as "Col2"
from
table1 a
join table1 b on a.col3 = b.col3
With some assumptions on the table structure, i.e. there exists exactly 2 entries in col3 for every unique value in col3.
DECLARE #table1 TABLE([col1] int, [col2] varchar, [col3] int);
INSERT INTO #table1(col1, col2, col3) VALUES(1, 'A', 1);
INTO #table1(col1, col2, col3) VALUES(2, 'B', 1);
INSERT INTO #table1(col1, col2, col3) VALUES(3, 'A', 2);
INSERT INTO #table1(col1, col2, col3) VALUES(4, 'D', 2);
INSERT INTO #table1(col1, col2, col3) VALUES(5, 'X', 3);
INSERT INTO #table1(col1, col2, col3) VALUES(6, 'G', 3);
SELECT
(SELECT TOP(1) t1.[col2] FROM #table1 AS t1 WHERE t1.[col3] = g.[GroupId] ORDER BY t1.[col1] ASC) AS [a],
(SELECT TOP(1) t2.[col2] FROM #table1 AS t2 WHERE t2.[col3] = g.[GroupId] ORDER BY t2.[col1] DESC) AS [b]
FROM
(SELECT DISTINCT u.col3 AS [GroupId] FROM #table1 AS u) AS g