Need to loop or iterate over a result set - sql

I have two columns Col1, Col2 from Table1 in database DB1. Col1 contains data and Col2 is all null. I have a column Col3 which comes from a query on Table2 in another database DB2. I want to set Col2 based on the following condition -
If a row of Col1 EQUAL TO any of the rows in Col3, then set Col2 EQUAL TO row of Col3. ELSE, set it EQUAL TO Col1. Its weird, but I need to do it.
Example -
Col3 is ALWAYS = {Aaa, RTY, Ccc, DART, Car, Fish, SPOON}
Col1,Col2,Col3
Aaa, null, Aaa
Bbb, null, RTY
Ccc, null, Ccc
...
How to make a query which will give us the result below ?
Col1,Col2,Col3
Aaa, Aaa, Aaa
Bbb, Bbb, RTY
Ccc, Ccc, Ccc
...

Assuming that you want to select rather than update - the most obvious solution to this would be in splitting up the problem into its individual bits:
Replace exy with your Col1, Col2, Col3 view/table/alias.
;WITH exy(Col1, Col2, Col3) AS (SELECT 'Aaa', null, 'Aaa' union SELECT 'Bbb', null, 'RTY' union SELECT 'Ccc', null, 'Ccc')
SELECT a.Col1, a.Col3 AS Col2, a.Col3 FROM exy AS a WHERE EXISTS (SELECT 1 FROM exy WHERE Col3 = a.Col3)
UNION
SELECT a.Col1, a.Col1 AS Col2, a.Col3 FROM exy AS a WHERE NOT EXISTS (SELECT 1 FROM exy WHERE Col3 = a.Col3)
Then you can simplify it down a little:
;WITH exy(Col1, Col2, Col3) AS (SELECT 'Aaa', null, 'Aaa' union SELECT 'Bbb', null, 'RTY' union SELECT 'Ccc', null, 'Ccc')
SELECT a.Col1, CASE WHEN 1 = EXISTS(SELECT 1 FROM exy WHERE Col3=a.Col3) THEN a.Col3 ELSE a.Col1 END AS Col2, a.Col3 FROM exy
There might be a nicer solution but we'd need to see your original tables and understand your problem. This can also be done with joins. But there is often benefit in clarity over performance. When performance is concerned, you will have to know what your targets are before optimising too early.

Could this work for your situation?
update t1
set col2 = coalesce(a.col3,a.col1)
from database1.dbo.table1 as t1 inner join (
select t1.col1
, t2.col3
from database1.dbo.table1 t1
left outer join (
select distinct col3
from database2.dbo.table2
) as t2 on t1.col1 = t2.col3
) as a on t1.col1 = a.col1
Set col2 to the first non-null value from either col3 or col1 from table 1 left outer joined to the distinct values in table 2, so when there is no match, col3 is null.

Related

Join or Union table with same Characteristics and different Measures

I would like to understand the easy/better way to join 2 tables with same characteristics and different measures as an example described below:
tab1
Col1
Col2
Measure1
1
1
10
1
2
5
tab2
Col1
Col2
Measure2
1
1
20
2
1
25
Expected Result
Col1
Col2
Measure1
Measure2
1
1
10
20
1
2
5
0
2
1
0
25
Questions:
How to avoid message: Ambiguous column name col1?
How to create a correct Join?
I have tried:
select col1, col2, t1.Measure1, t2.Measure2
from tab1 t1
full outer jon tab2 t2
on t1.col1 = t2.col1
and t1.col2 = t2.col2
I have tried a Union and it works, but i am looking a easy way using joins:
Select col1, col2, Measure1, 0 as Measure2 From tab1
Union
Select col1, col2, 0 as Measure1, Measure2 From tab2
The full join is the correct approach. But you need to disambiguate col1 and col2 in the select clause: both tables have both columns, so it is unclear to which column an unprefixed col1 refers.
A typical approach uses coalesce():
select
coalesce(t1.col1, t2.col1) col1,
coalesce(t1.col2, t2.col2) col2,
coalesce(t1.measure1, 0) measure1,
coalesce(t2.measure2, 0) measure2
from tab1 t1
full outer jon tab2 t2
on t1.col1 = t2.col1 and t1.col2 = t2.col2
Note that you also need coalesce() around the measures to return 0 instead of null on "missing" values.
In some databases (eg Postgres), you can use the using syntax to declare the join conditions for columns that have the same name across the tables ; this syntax automagically disambiguates the unprefixed column names, so:
select
col1,
col2,
coalesce(t1.measure1, 0) measure1,
coalesce(t2.measure2, 0) measure2
from tab1 t1
full join tab2 t2 using (col1, col2)
You should reference source tables for col1 and col2 as well.
As you're using FULL OUTER JOIN I'd recommend using COALESCE statement.
SELECT COALESCE(t1.col1, t2.col1) as col1,
COALESCE(t1.col2, t2.col2) as col2,
t1.Measure1,
t2.Measure2
FROM tab1 t1
FULL OUTER JOIN tab2 t2
on t1.col1 = t2.col1
and t1.col2 = t2.col2

Insert into one table from another Postgres based on two columns

I have two tables with the same columns, There are no unique columns for these tables. Lets say the columns are Col1, Col2, Col3 and Col4. The tables are T1 and T2.
What I want to do is insert all the rows from T2 to T1 where Col1 & Col2 combinations do not exist in T1 already. Col1 is a string and Col2 is an int.
So for example Col1 = "APPLE" and Col2 = "2019". If a row contains Col1 = "APPLE" and Col2=2019 in T2 I do not want to insert it into T1 whereas if a row contains Col1 = "APPLE" and Col2=2020 then I want to insert it into T1.
I am trying to find the easiest solution to do this and cant seem to find a straightforward way using INSERT INTO WHERE NOT EXISTS or using UPSERT.
You can use insert ... select ... where not exists with tuple equality to compare (col1, col2):
insert into t1(col1, col2, col3, col4)
select * from t2
where not exists (
select 1 from t1 where (t1.col1, t1.col2) = (t2.col1, t2.col2)
)
With NOT EXISTS:
insert into t1(Col1, Col2, Col3, Col4)
select Col1, Col2, Col3, Col4
from t2
where not exists (
select 1 from t1
where t1.Col1 = t2.Col1 and t1.Col2 = t2.Col2
)
See a simplified demo.

copy a table into a new table and add a new column on SQL server 2008

I need to copy a table into a new table on SQL server 2008.
Also, add a new column into the new table.
The values of the new column depends on the compare result between the new table and another table.
Example,
Table1:
col1 col2 col3
abc 346 6546
hth 549 974
Expected Table1_new:
col1 col2 col3 col4
abc 346 6546 1
hth 549 974 0
Table2:
col1
abc
sfsdf
If Table2's col1 appear in Table1 col1, mark col4 as 1 in Table1_new, else mark as 0.
The code does not work
SELECT *,
(
SELECT 1 as col4
FROM Table2 as a
INNER JOIN Table1 as b
on b.col1 = a.col1
SELECT 0 as col4
FROM Table2 as a
INNER JOIN Table1 as b
on b.col1 <> a.col1 # I do not know how to do this !!!
)
INTO table1_new
FROM table1
Any help would be appreciated.
You could use an outer join:
SELECT table1.col1, col2, col3,
CASE WHEN table2.col1 IS NULL THEN 0 ELSE 1 END AS col4
INTO table1_new
FROM table1
LEFT OUTER JOIN table2 ON table1.col1 = table2.col1
You can do this in several ways. The following uses an exists clause in a case statement:
insert into table1_new(col1, col2, col3, col4)
select col1, col2, col3,
(case when exists (select 1 from table2 t2 where t2.col1 = t1.col1)
then 1 else 0
end)
from table1 t1;
You can also do this with a left outer join, but you run the risk of duplicates if t2 has duplicates.
INSERT INTO T2
SELECT COL1,COL2,COL3, (COL1+COL2) FROM T1
Note that instead of the (COL1+COL2) section you could run other expressions or possibly even a function.
Try something like this using CASE
SELECT
CASE
WHEN b.col1 = a.col1 THEN 1
ELSE 0
END as col4
FROM Table1 as a
LEFT JOIN Table2 as b
on b.col1 = a.col1
EDIT: Table1 should be the left table as mentioned in #Muerniks answer.
In addition to what the others already suggested: If you can't solve the problem in one step, try to make smaller steps. E.g. first initialize Table1.col4 with zero:
INSERT INTO Table1_new (col1,col2,col3,col4)
SELECT col1,col2,col3,0
FROM Table1
After that you will only need to identify the records which have matching partners in Table2 which is a classical inner join:
UPDATE t1 SET col4=1
FROM Table1_new t1
JOIN Table2 t2 ON t2.col1=t1.col1

SQL Server Query to find different names in two tables

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

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