SQL Server: compare two tables and populate flag column - sql

i need to populate flag column after comparing data from two tables.
i have tables A and B.
Table A:
NAME----PHONE-----ID1---------ID2
MAT------123456-----0.123-----2.123
NICK-----234672----123-------234
SAM-----111111-----456------987
Table B columns are
ID_A, ID_B, ID_C, ID_D,,,so on.. and has data similar to ID1 and ID2 on Table A
If ID1 or ID2 from Table A matches any values on Table b for respective row then put 'Y' on the flag column of Table B.
requirement is pretty straight but i am not sure how to start coding .any help would be appreciated.

If I understand correctly, you can do this with a case statement and exists clause:
select b.*,
(case when exists (select 1
from tableA a
where a.id1 in (b.id_a, b.id_b, b.id_c, b.id_d) or
a.id2 in (b.id_a, b.id_b, b.id_c, b.id_d)
)
then 'Y'
else 'N'
end) as flag
from tableB b;
EDIT:
If you actually want an update:
update b
set flag = (case when exists (select 1
from tableA a
where a.id1 in (b.id_a, b.id_b, b.id_c, b.id_d) or
a.id2 in (b.id_a, b.id_b, b.id_c, b.id_d)
)
then 'Y'
else 'N'
end);

Try this:
UPDATE b
SET Flag = CASE WHEN EXISTS
(
SELECT x.ID FROM
(
SELECT b.ID_A UNION ALL
SELECT b.ID_B UNION ALL
SELECT b.ID_C UNION ALL
SELECT b.ID_D UNION ALL
SELECT b.ID_E
) x(ID) WHERE x.ID IS NOT NULL
INTERSECT
SELECT y.ID FROM dbo.TableA a CROSS APPLY
(
SELECT a.ID1
UNION ALL
SELECT a.ID2
) y(ID) WHERE y.ID IS NOT NULL
) THEN 'Y' ELSE 'N' END
FROM dbo.TableB b;

Related

Table Join condition

I have two tables
Table A :
Item Lookup
A X
B null
C Y
D K
Table B :
Lookup
X
Y
Z
I want to join these tables and get output like
Item Lookup
A X
B null
C Y
I wanna pick up all matching lookup and as well as null lookups in my output view. can anyone tell me the join condition
It looks like you want rows in A that either match B or have a NULL lookup. You would do this with an inner join and a special condition:
select distinct a.item, a.lookup
from tableA a join
tableB b
on (a.lookup = b.lookup) or (a.lookup is NULL);
If you have an index on lookup, then exists is better for performance:
select a.item, a.lookup
from tableA a
where a.lookup is null or
exists (select 1 from tableB b where b.lookup = a.lookup);
EDIT:
Using a left join with a where condition is also possible:
select distinct a.item, a.lookup
from tableA a left join
tableB b
on a.lookup = b.lookup
where (a.lookup is NULL and b.lookup is NULL) or
b.lookup is not null;
The following query will return all records of TableA that have Lookup in TableB, or have a NULL Lookup:
SELECT Item, Lookup
FROM TableA
WHERE (Lookup IS NULL) OR Lookup IN (SELECT Lookup FROM TableB)
I think this will help
SELECT DISTINCT A.Item, A.Lookup FROM A, B WHERE A.lookup=B.lookup OR A.lookup IS NULL
You can do also do it via a left outer join:
with tablea as (select 'A' item, 'X' lookup from dual union all
select 'B' item, null lookup from dual union all
select 'C' item, 'Y' lookup from dual union all
select 'D' item, 'K' lookup from dual),
tableb as (select 'X' lookup from dual union all
select 'Y' lookup from dual union all
select 'Z' lookup from dual)
select a.item,
a.lookup
from tableA a
left outer join tableB b on (a.lookup = b.lookup)
where a.lookup is null
or a.lookup = b.lookup;
ITEM LOOKUP
---- ------
A X
C Y
B

compare two tables on SQL server with result to show which column from its associated table

I need to compare two tables on SQL server.
table1
id value
3 5
table2
id value
8 6
SELECT *
FROM
(
SELECT a.id AS a_id, a.value AS a_value
FROM [table1] as a
UNION ALL
SELECT b.id AS b_id, b.value AS b_value
FROM [table2] as b
) tmp
GROUP BY tmp.a_id, tmp.a_value
HAVING COUNT(*) = 1
ORDER BY tmp.a_id
I get result:
a_id a_value
3 5
8 6
I need to know which column is from which table, e.g.
a_id a_value b_id b_value
3 5 8 6
Any help would be appreciated !
Thanks !
What about:
SELECT *
FROM (
SELECT a.id, a.value, 'Table1' AS TableName
FROM [table1] as a
UNION ALL
SELECT b.id, b.value, 'Table2' AS TableName
FROM [table2] as b
) tmp
GROUP BY tmp.id, tmp.value, tmp.TableName
HAVING COUNT(*) = 1
ORDER BY tmp.id
You could add a column for tbl. Something like:
SELECT
m.id
,m.value
INTO #tmp
FROM
(
SELECT a.id AS id, a.value AS value
FROM [table1] as a
UNION ALL
SELECT b.id AS id, b.value AS value
FROM [table2] as b
) m
GROUP BY
m.id
,m.value
HAVING COUNT(*) = 1
CREATE CLUSTERED INDEX ix_tmpidvalue ON #tmp
(
id ASC
,value ASC
)
SELECT *
FROM
(
SELECT a.id AS id, a.value AS value, 'a' tbl
FROM [table1] as a
UNION ALL
SELECT b.id AS id, b.value AS value, 'b' tbl
FROM [table2] as b
) tmp
WHERE EXISTS
(
SELECT 1
FROM #tmp n
WHERE tmp.id = n.id
AND tmp.value = n.value
)
ORDER BY tmp.id

How to LEFT JOIN in DB2 iseries with first row?

I have need a query that JOIN a TABLE with A first row of other table value based:
SELECT * FROM TABLEA A LEFT JOIN
(SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
but DB2 return ERROR because can't use A.CODE
How can solve this?
You need to use the nested table expression:
SELECT * FROM TABLEA A LEFT JOIN
LATERAL (SELECT * from TABLEB
WHERE FIELD1 <> '3' and FIELD2 = 'D' AND A.CODE=CODE
FETCH FIRST 1 ROW ONLY
) B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
This is a highly optimized statement.
Your not getting any data from tableb and your going for first row so you just need exists clause.
select a.* from tablea a
where exists (select * from tableb b
where a.fielda = b.fielda
and a.fieldb = b.fieldb
and b.code = a.code
and b.field2 = 'd' and b.field1 <> '3')
You can use the OLAP function row_number() to rank the records according to somefield(s) within a (fielda,fieldb,code) group. Somefield might be a transaction id, or sequence, for example. The order by clause is optional there, but without it, you might be randomly picking which record is the first in the group.
WITH B AS
(SELECT *,
row_number() over (partition by fielda,fieldb,code
order by somefield
) as pick
from TABLEB
WHERE FIELD1 <> '3'
and FIELD2 = 'D'
)
SELECT *
FROM TABLEA A LEFT JOIN B
on a.FIELDA = b.FIELDA
and A.FIELDB = B.FIELDB
and A.CODE = B.CODE
where pick=1

Oracle sql query union operation?

I have two tables. TableA and TableB. both the tables has some data with two columns as below.
TableA
---------
id Name
--- ----
1 abc
2 def
TableB
---------
id Name
--- ----
1 xyz
2 pqr
Now i would pass list of ids from my application and get same ids along with their names as:
select id, name
from TableA
where id in(1,2)
union select id, name
from TableB
where id in(1,2);
above query gives results as:
1 abc
1 xyz
2 def
2 pqr
But what i need is if same id is present in both the tables then TableB's Name should be considered but not TableA's name.
Expected output:
1 xyz
2 pqr
One more is, if TableB does not contain any data then TableA's data should be fetched.
How can i do that?
Thanks!
Please try using LEFT JOIN.
SELECT TableA.ID,
NVL(TableB.Name, TableA.Name) Name FROM
TableA LEFT JOIN TableB
ON TableA.ID=TableB.ID
WHERE TableA.ID IN (1, 2)
Try this query using simple union you can club the records
SELECT id, name from tableA where id not in (SELECT id FROM tableB)
UNION ALL
SELECT id, name from tableB
Try this:
select id, name from TableA where id in(1,2) and id not in ( select id from TableB) a union select id, name from TableB where id in(1,2);
try this
SELECT id , name from (
select id, name from TableA where id in(1,2)
union select id, name from TableB where id in(1,2)) t
GROUP BY id;
Use Union All, and exists/not exists to control which results are returned from table_a based on the existence of any records in table_b
select id,name
from (
select id,name
from table_b
union all
select id,name
from table_a
where exists (select null from table_b) and
not exists (
select null
from table_b
where table_b.id = table_a.id)
union all
select id,name
from table_a
where not exists (select null from table_b))
where id in (1,2)
http://sqlfiddle.com/#!4/36f26/3
one way of doing it if rows can be in A, A+B or B is (if tablea always has data, then techdo's answer is better):
select id, name
from (select id, name, row_number() over (partition by id order by rnk) rn
from (select id, name, 1 rnk from tableb
union all
select id, name, 2 rnk from tablea))
where rn = 1;
SELECT (case when B.id = A.id then b.id else a.id end) as id,
(case when B.id = A.id then b.name else a.name end) as name
FROM tableA a left JOIN tableB b ON (a.id = b.id)
MINUS operator - returns only unique rows returned by the first query but not by the second:
WITH tab_a AS
(
SELECT 1 id, 'abc' val FROM dual
UNION
SELECT 2, 'def' FROM dual
),
tab_b AS
(
SELECT 1, 'xyz' val FROM dual
UNION
SELECT 2, 'pqr' FROM dual
)
-- This is your query --
SELECT * FROM tab_b
MINUS
SELECT * FROM tab_a
/
ID VAL
----------
1 xyz
2 pqr
Following code is for selecting data from both the tables(A +B) and then taking out data using minus and join for the rows not required. Code can be easily modified if the requirement changes from selecting names from table A instead of table B.
select * from tableA where id in (1,2)
union
select * from tableB where id in (1,4)
minus
select a,id, a.Name from tableA a join tableB b on a.id = b.id where
a.id in (1,2);

Need to simplify multiple Select queries

This is the structure of my existing SQL query :
SELECT * FROM (
SELECT *, 'A' AS Status FROM Table1
WHERE Field1 NOT IN
(
SELECT Field1 FROM Table2 WHERE Field 1 = 'val' AND ...
)
UNION
SELECT *, 'B' AS Status FROM Table1
WHERE Field1 IN
(
SELECT Field1 FROM Table2 WHERE Field 1 = 'val' AND ...
)
) AS Result
Here I'm selecting two sets of data from a table and assigning two different values (A & B) for the Status column and Union both sets in to one as Result.
Problem with this method is, it needs to duplicate the inner select query SELECT Field1 FROM Table2 WHERE Field 1 = 'val' AND ... (my original sql query is bit complex than the shown above)
How can I rewrite this as a single Select query? Is it possible or not?
You could simply move the WHERE condition to a CASE expression, like this:
SELECT
*,
CASE
WHEN Field1 IN (
SELECT Field1 FROM Table2 WHERE Field1 = 'val' AND ...
)
THEN 'B'
ELSE 'A'
END AS Status
FROM Table1
;
You could also use a LEFT JOIN method like others suggested, but if Table2 produces duplicates for the specified filter, you might get duplicates in the output as well. To avoid that, you would probably need to use a derived table that only returns distinct values, something like this:
SELECT
t1.*,
CASE
WHEN t2.Field1 IS NULL THEN 'A'
ELSE 'B'
END AS Status
FROM Table1 t1
LEFT JOIN (
SELECT DISTINCT Field1 FROM Table2 WHERE Field1 = 'val' AND ...
) t2
ON t1.Field1 = t2.Field2
;
you can simply use LEFT JOIN on this,
SELECT a.*,
CASE WHEN b.field1 IS NULL
THEN 'A'
ELSE 'B'
END AS Status
FROM table1 a
LEFT JOIN table2 b
ON a.field1 = b.field1 AND
b.field1 = 'VAL'
Please check the below query, which works if there is only one condition of Field1=’val’ on Table2. If there are multiple where conditions, then go for LEFT JOIN.
SELECT
*,
(CASE WHEN Field1='val' THEN 'B' ELSE 'A' END) AS Status
FROM
Table1
U can achieve this by using LEFT JOIN and CASE as follows
SELECT a.*,
(CASE b.Field1
WHEN 'Val'
THEN 'B' ELSE 'A' END) as status
FROM Table1 a LEFT JOIN Table2 b ON a.field1 =b.field1
If multiple conditions are there for status try the following one
SELECT a.*,
(CASE
WHEN (SELECT COUNT(Field1)
FROM Table2
WHERE field1 =a.field1 AND Field 1 ='val' AND ...) >0
THEN 'B' ELSE 'A' END) as status
FROM Table1 a LEFT JOIN Table2 b ON a.field1 =b.field1