Table Join condition - sql

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

Related

Is there a way to JOIN a table consisting of two tables UNIONed together?

SELECT
a.First_Name
,b.Last_Name
FROM table a
JOIN table b
UNION table c
ON a.ID=b.ID
I'm not even sure how the syntax would be for this. Basically what I want is to UNION table b and c then JOIN the new table to table a.
You can join a subquery:
SELECT
a.First_Name,
bc.Last_Name
FROM a
JOIN
(
SELECT ID, Last_Name FROM b
UNION
SELECT ID, Last_Name FROM c
) bc ON bc.ID = a.ID;
Make the union a subquery:
SELECT
a.First_Name
,bc.Last_Name
FROM table a
JOIN (
SELECT * FROM table b
UNION
SELECT * FROM table c
) AS bc
ON a.ID=bc.ID
Note that the subquery must have its own alias (bc in this case) which should be referenced in the join clause and the select (meaning you can't reference tables b or c directly outside of the subquery).
The result of a union can be join to others table if you the the proper join clause
You could use this sintax
select a.col1, t.name
from table3 c
inner join (
select id, name1 as name
from table1 a
union id, name2
from table2 b
) t on. t.id = a.id

XOR JOIN in SQL

I have the following tables
Table A
ID "Other Columns"
1
2
3
Table B
ID "Other Columns"
3
4
5
What is the efficient way to return the below result?
Result
ID "Other Columns"
1
2
4
5
A full outer join should work, and only go through each table once. They can be tricky, so test carefully!
SELECT
isnull(A.ID, B.ID) ID
,"Other columns" -- Handle nulls properly!
from TableA A
full outer joing TableB B
on B.ID = A.ID
where not (A.ID is not null
and B.ID is not null)
You want to use left and right join and union them
Select TableA.ID as 'ID','Other Colums'
FROM TableA Left join TableB
ON TableA.ID=TableB.ID
WHERE TableB.ID IS NULL
UNION
Select TableB.ID as 'ID','Other Colums'
FROM TableA Right join TableB
ON TableA.ID=TableB.ID
WHERE TableA.ID IS NULL
You can try like this
SELECT
COALESCE(a.id, b.id),
OtherColumns
FROM #tablea a
FULL JOIN #tableb b
ON a.id = b.id
WHERE a.id IS NULL
OR b.id IS NULL
You can do this with a UNION ALL using a LEFT JOIN to determine if the ID is not in the other table. Keep in mind that the column count and datatypes between the two tables must match up:
Select A.Id, A.OtherColumns
From TableA A
Left Join TableB B On A.Id = B.Id
Where B.Id Is Null
Union All
Select B.Id, B.OtherColumns
From TableB B
Left Join TableA A On A.Id = B.Id
Where A.Id Is Null
Not quite sure what you need with the "Other columns", but you could use EXCEPT:
Select ID from TableA
EXCEPT
Select ID from TableB
If you need Other columns from TableA you could use:
Select ID, OtherColumn1, OtherColumn2 from TableA
where ID not in (select ID from TableB)
(as long as ID cannot be null in TableB)
I broke down each part to be clearer!
select *
into #temp
from
TabA Full outer join TabB
on TabA.ColNameA = TabB.ColNameB
select *
into #temp2
from #temp
where (ColNameA is Null Or ColNameB is null)
select ColNameA from #temp2
where ColNameA Is not null
union
select ColNameB from #temp2
where ColNameB Is not null

Multiple Join to single column using ID T-SQL

I have following issue. I'm trying to join three tables:
TableA: Record_id, Reference_id, Param
TableB: Doc_id, NameB
TableC: Doc_id, NameC
depending on value in TableA.Param, I need to select Name from tables B or C by joining on Reference_id
I've tried to use "case" constrain, but didn't worked out :)
select a.Record_id, a.Reference_id
, case when Param = 'B' then b.NameB
when Param = 'C' then c.NameC
from TableA as a inner join
TableB as b on a.Reference_id = b.Doc_id inner join
TableC as c on a.Reference_id = c.Doc_id
Any ideas?
You could left join with that condition and take the first non-null name with coalesce()
select a.Record_id, a.Reference_id,
coalesce(b.NameB, c.NameC) as name
from TableA as a
left join TableB as b on a.Reference_id = b.Doc_id
and Param = 'B'
and b.STAT = 'A'
left join TableC as c on a.Reference_id = c.Doc_id
and Param = 'C'
and c.STAT = 'A'
BTW your query was close (missed the end). This would have worked with left joins
select a.Record_id, a.Reference_id,
case when Param = 'B' then b.NameB
when Param = 'C' then c.NameC
end as name
from TableA as a
left join TableB as b on a.Reference_id = b.Doc_id and b.STAT = 'A'
left join TableC as c on a.Reference_id = c.Doc_id and c.STAT = 'A'
SELECT a.Record_id, a.Reference_id,V.Name
FROM TableA AS a
inner join
(
SELECT Doc_id id, NameB Name,'B' Type from TableB
UNION ALL
SELECT Doc_id ID, NameC name,'C' Type From TableC
) AS V On V.ID=Reference_id AND Type=Param
Try this:
SELECT a.Record_id, a.Reference_id, b.NameB AS Name
FROM TableA AS a
INNER JOIN TableB AS b ON a.Reference_id = b.Doc_id
WHERE a.Param = 'B'
UNION
SELECT a.Record_id, a.Reference_id, c.NameC AS Name
FROM TableA AS a
INNER JOIN TableC as c ON a.Reference_id = c.Doc_id
WHERE c.Param = 'C'

SQL Server Custom sorting in ORDER BY clause

ALTER PROCEDURE sp_1
AS
BEGIN
SELECT B.ID, 'B' AS Name
FROM tableB inner join table a inner join table c
UNION
SELECT A.ID, 'A' AS NAME
FROM tableA inner join table b inner join table c
UNION
SELECT C.ID, 'C' AS NAME
FROM tableC inner join table a inner join table b
ORDER BY CASE WHEN Name = 'A' THEN '1'
ELSE Name END ASC
END
The code above returns invalid column name 'Name'. Is there anyway where i can sort 'name customly by using order by without delcaring any new paramters.
SELECT B.ID, 'B' AS Name, 1 as ExplicitOrderGroup
FROM tableB inner join table a inner join table c
UNION
SELECT A.ID, 'A' AS NAME, 0 as ExplicitOrderGroup
FROM tableA inner join table b inner join table c
UNION
SELECT C.ID, 'C' AS NAME, 1 as ExplicitOrderGroup
FROM tableC inner join table a inner join table b
ORDER BY ExplicitOrderGroup, Name
Note, UNION (which behaves a bit like DISTINCT) will not collaps now same rows with different ExplicitOrderGroup. You have to determine whethere it's OK or you need some other behaviour.
You can't use alias in order by you have to use concrete column but you can achieve this easily using common table expression for example
WITH MY_CTE (col1, col2, col3)
AS
-- Define the CTE query.
(
SELECT col1, prop2 as col2, col3
FROM table
)
-- Define the outer query referencing the CTE name.
SELECT col1, col2, col3
FROM MY_CTE
ORDER BY col2
GO
This is just an example to point u in direction
Can achieve this by sub-query without any new variable/parameter
ALTER PROCEDURE sp_1
AS
BEGIN
SELECT SQ.ID, SQ.Name FROM (
SELECT B.ID, 'B' AS Name
FROM table B inner join table a inner join table c
UNION
SELECT A.ID, 'A' AS NAME
FROM table A inner join table b inner join table c
UNION
SELECT C.ID, 'C' AS NAME
FROM table C inner join table a inner join table b
) SQ
ORDER BY CASE WHEN SQ.Name = 'A' THEN '1'
ELSE SQ.Name END ASC
END
In this case I would add an extra column for priority.
Like this:
ALTER PROCEDURE sp_1
AS
BEGIN
SELECT B.ID, 'B' AS Name, 2 AS prio
FROM tableB inner join table a inner join table c
UNION
SELECT A.ID, 'A' AS NAME, 1 AS prio
FROM tableA inner join table b inner join table c
UNION
SELECT C.ID, 'C' AS NAME, 2 AS prio
FROM tableC inner join table a inner join table b
ORDER BY prio ASC, Name ASC
END

SQL Server: compare two tables and populate flag column

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;