SQL join different tables depending on row information - sql

Suppose I have table A with a field that can be either 1 or 2...
How do I select such that for each row in table A, if the field is 1, join the select with table B and if the field is 2, join the select with table C?

(
SELECT MyField1, MyField2 FROM A
INNER JOIN B ON A.Id = B.Id
AND A.MyField = 1
)
UNION
(
SELECT MyField1, MyField2 FROM A
INNER JOIN C ON A.Id = C.Id
AND A.MyField = 2
)

Somethine like this can work
DECLARE #TableA TABLE(
ID INT
)
DECLARE #TableB TABLE(
ID INT,
Val VARCHAR(50)
)
DECLARE #TableC TABLE(
ID INT,
Val VARCHAR(50)
)
INSERT INTO #TableA SELECT 1
INSERT INTO #TableA SELECT 2
INSERT INTO #TableB SELECT 1, 'B'
INSERT INTO #TableC SELECT 2, 'C'
SELECT *
FROM #TableA a INNER JOIN
#TableB b ON a.ID = b.ID
AND a.ID = 1
UNION
SELECT *
FROM #TableA a INNER JOIN
#TableC c ON a.ID = c.ID
AND a.ID = 2

Related

Set multiple variables and case statement in 1 query

I have
table a with columns lot and tid
table b with columns lot and id
table t with columns id and flag
One of my query set variable #ID to the below query whose flag = 'Y'
The 2nd query set variable #ID_Not_Flag to the below query whose flag <> 'Y'
Can I do the below queries (set #ID and #ID_Not_Flag) in 1 query?
SELECT #ID = a.tid
FROM a, b, t
WHERE b.lot = a.lot and b.id =123 and t.id = a.tid and flag = 'Y'
SELECT #ID_Not_Flag = a.tid
FROM a, b, t
WHERE b.lot = a.lot and b.id =123 and t.id = a.tid and flag <> 'Y'
Table a
lot tid
100 1
100 2
Table b
lot id
100 123
Table t
id flag
1 Y
2 N
Desired result from 1 query:
#ID = 1, #ID_Not_Flag = 2
The below query result in #ID = 1, #ID_Not_Flag = NULL
SELECT
#ID = (CASE WHEN flag = 'Y' THEN a.tid END),
#ID_Not_Flag = (CASE WHEN flag <> 'Y' THEN a.tid END)
FROM a, b, t
WHERE b.lot = a.lot and b.id =123 and t.id = a.tid
SELECT #ID,#ID_Not_Flag
Result (not correct):
ID ID_Not_Flag
1 NULL
You can try a pivot table. The first part of the query is just creating temp tables to hold the data.
/*CREATE TEMP TABLES*/
DECLARE #a TABLE ( lot int, tid int)
DECLARE #b TABLE ( lot int, id int)
DECLARE #t TABLE ( id int, flag VARCHAR(1))
INSERT INTO #a (lot, tid) VALUES (100, 1) , (100, 2)
INSERT INTO #b (lot, id) VALUES (100, 123)
INSERT INTO #t (id, flag) VALUES (1, 'Y') , (2, 'N')
/*QUERY*/
SELECT [Y] [#id] ,
[N] [#id_not_flag]
FROM (
SELECT a.lot, a.tid, b.id , t.flag
--,ID = (CASE WHEN flag = 'Y' THEN a.tid END)
--,ID_Not_Flag = (CASE WHEN flag <> 'Y' THEN a.tid END)
FROM #a a
LEFT JOIN #b b
ON a.lot = b.lot
LEFT JOIN #t t
ON t.id = a.tid) AS Src
PIVOT (max(Src.tid) FOR flag in ([Y] , [N])) Pvt
You can just use another join and COALESCE
Example returns 1 2
DECLARE #a Table(lot INT,tid INT);
DECLARE #b Table(lot int ,id INT);
DECLARE #t Table(id INT,flag CHAR);
INSERT INTO #a(lot, tid)
values
(100, 1),
(100, 2);
INSERT INTO #b(lot, id)
values
(100, 123)
INSERT INTO #t(id, flag)
values
(1, 'Y'),
(2, 'N');
--SELECT * FROM #a;
--SELECT * FROM #b;
--SELECT * FROM #t;
DECLARE
#ID INT,
#ID_Not_Flag INT;
SELECT
#ID = COALESCE(ty.id,#ID),
#ID_Not_Flag = COALESCE(tn.id, #ID_Not_Flag )
FROM #b AS b
INNER JOIN #a AS a ON b.lot = a.lot
LEFT OUTER JOIN #t AS ty ON ty.id = a.tid AND ty.flag = 'Y'
LEFT OUTER JOIN #t AS tn ON tn.id = a.tid AND tn.flag = 'N'
WHERE b.id = 123;
SELECT #ID , #ID_Not_Flag ;

How to capture columns from joined tables using output clause?

I am updating a table called tableA by joining tableB and tableC at the same time I am capturing updated records into temp table using output clause from tableA . Now I want capture columns from table B for the updated data but output clause isn't allowing the same.
Eg:
Update SLC Set SLC.Datascrublevel = C.Datascrublevel
OUTPUT [Deleted].Systemcode,
[Deleted].Systemkey,
[Deleted].datascrublevel,
[Inserted].datascrublevel
INTO #TEMP1
FROM TABLEA SLC with(nolock)
INNER JOIN TABLEB SC ON SC.SystemCode = SLC.SystemCode
INNER JOIN TABLEC SL ON SL.SystemCode = SLC.SystemCode and SLC.SystemKey = SL.Systemkey
INNER JOIN #TEMP C ON SLC.Datascrublevel <> C.DataScrubLevel AND C.Systemcode = SLC.SystemCode and C.Systemkey = SLC.SystemKey
Now I want columns from tableB to capture into temp table using output clause. Please provide your advise if there are any alternative ways.
Just Like you have given it as [deleted].[Column Name] and [Inserted].[Column Name] add one more column as [SC].[Column Name]
Example :
IF OBJECT_ID('TempDb..#TABLEA') IS NOT NULL
DROP TABLE #TABLEA
IF OBJECT_ID('TempDb..#TABLEB') IS NOT NULL
DROP TABLE #TABLEB
IF OBJECT_ID('TempDb..#TABLEC') IS NOT NULL
DROP TABLE #TABLEC
IF OBJECT_ID('TempDb..#TABLED') IS NOT NULL
DROP TABLE #TABLED
CREATE TABLE #TABLEA
(
SeqNo INT IDENTITY(1,1),
MyDate DATE
)
CREATE TABLE #TABLEB
(
SeqNo INT IDENTITY(1,1),
FullName VARCHAR(20)
)
CREATE TABLE #TABLEC
(
SeqNo INT IDENTITY(1,1),
FullName VARCHAR(20),
MyDate DATE
)
CREATE TABLE #TABLED
(
SeqNo INT,
MyDate DATE,
FullName VARCHAR(20)
)
INSERT INTO #TABLEA
(
MyDate
)
SELECT GETDATE()
UNION
SELECT GETDATE()+1
UNION
SELECT GETDATE()-1
INSERT INTO #TABLEB
(
FullName
)
VALUES('A'),('B'),('C')
INSERT INTO #TABLEC
(
FullName
)
VALUES('A'),('B'),('C')
UPDATE C
SET MyDate = A.MyDate
OUTPUT
deleted.SeqNo,
deleted.MyDate,
B.FullName
INTO #TABLED
FROM #TABLEC C
INNER JOIN #TABLEB B
ON C.FullName = B.FullName
INNER JOIN #TABLEA A
ON A.SeqNo = B.SeqNo
SELECT * FROM #TABLED

How to Select rows in a table with all matching conditions in joining table

I have two tables (table A) and (table B) and one table variable (#country) that will build the where condition for finding out the list of employees matching the countries.
TableA(empId, name)
(1,John),(2,Mary),(3,Harry)
TableB(empId, country)
(1,Australia),(1,US),(1,UK),(2,US)
For example, I need to select only those employees from TableA who have resides in both Australia and US. i.e. emp 1 (John). The query should be able to handle more countries in where clause if require. This depends on the number of countries in table variable #country.
I have tried many option including the following query but nothing seems to work.
DECLARE #country TABLE (
[country] [nvarchar](255) NOT NULL
);
insert into #country (country) values('Australia'),('US')
Select E.empID, EC.empID,EC.country from TableA E
INNER JOIN TableB EC on E.empID= EC.empID
Where EC.country = ALL(Select country from #country)
Could you please advise on how to write the best query to achieve this task? Please note that #country can have one or more countries.
Try:
SELECT E.empID
,EC.empID
,EC.country
FROM TableA E
INNER JOIN TableB EC
ON E.empID = EC.empID
WHERE EXISTS (
SELECT 1
FROM TableB EC_US
WHERE EC_US.empID = EC.empID
and EC_US.Country = 'US'
)
AND EXISTS (
SELECT 1
FROM TableB EC_Aus
WHERE EC_Aus.empID = EC.empID
and EC_Aus.Country = 'Australia'
)
Or:
SELECT E.empID
,EC.empID
,EC.country
FROM TableA E
INNER JOIN TableB EC
ON E.empID = EC.empID
WHERE EC.empID IN (
SELECT EC_Sub.empID
FROM TableB EC_Sub
WHERE EC_Sub.Country IN ('Australia','US')
GROUP BY EC_Sub.empID
HAVING COUNT(*) = 2
)
Try Now, added where clause. Change any value of #country and execute the query:
DECLARE #TableA TABLE (empId INT, [Name] VARCHAR(100))
INSERT INTO #TableA VALUES (1, 'John')
INSERT INTO #TableA VALUES (2, 'Mary')
INSERT INTO #TableA VALUES (3, 'Harry')
DECLARE #TableB TABLE (empID INT, country VARCHAR(100))
INSERT INTO #TableB VALUES (1, 'Australia')
INSERT INTO #TableB VALUES (1, 'UK')
INSERT INTO #TableB VALUES (2, 'US')
DECLARE #country TABLE ([country] [nvarchar](255) NOT NULL);
INSERT INTO #country (country) VALUES('Australia'),('US')
SELECT a.* , tb.country
FROM #TableA AS a
INNER JOIN (
SELECT b.empid,
COUNT(*) AS empInMultipleCountry
FROM #TableB b
GROUP BY
empid
) b
ON a.empId = b.empid
INNER JOIN #TableB AS tb
ON tb.empId = a.empId
WHERE empInMultipleCountry > 1
AND EXISTS (SELECT 1 FROM #country AS c WHERE c.country = tb.country)
Select E.empID, EC.empID,EC.country
from TableA E INNER JOIN TableB EC on E.empID= EC.empID
Where EC.country IN ('Australia','US');

Set column values in TableA to corresponding values from TableB if some value exist in TableC

I have a TableA that I just added two columns to, StartDate and StopDate. It also contain the column UserName.
I want to fill it with values from TableB that also has StartDate and StopDate. TableB has another column called UserId.
TableC has two columns, Id and Name.
This is what I want to do, explained with some kind of pseudocode:
for each row in TableB, where TableB.UserId exists in TableC.Id, take the corresponding row in TableA where TableA.UserName = TableC.Name and set the TableA.StartDate = TableB.StartDate & TableA.StopDate = TableB.StopDate.
I tried to create a join statement that would do it but the result was kind of embarrassing.
Help would be much appreciated.
Edit: What I have tried:
UPDATE TableA
SET STARTDATE = (
SELECT TableB.StartDate
FROM TableB
WHERE TableB.UserId = (??? what should I write here)?
And then same for StopDate
You can achieve this using the "update-from" syntax.
*I see you've already solved your question, but I'll post this as a possible alternative.
declare #TableA table (id int identity(1, 1), startDate datetime, stopDate datetime, userName varchar(20))
declare #TableB table (id int identity(1, 1), startDate datetime, stopDate datetime, userId int)
declare #TableC table (userId int, userName varchar(20))
insert into #TableA (userName)
select 'A' union all select 'B'
insert into #TableB (userId, startDate, stopDate)
select 1, '2015-01-01', '2015-01-31' union all select 2, '2015-12-01', '2015-12-31'
insert into #TableC
select 1, 'A' union all select 2, 'B'
update
A
set
A.startDate = B.startDate,
A.stopDate = B.stopDate
from
#TableA A
inner join #TableC C on C.userName = A.userName
inner join #TableB B on B.userId = C.userId
select
*
from
#TableA
I solved it, here is my solution
UPDATE TableA
SET StartDate = up.StartDate, EndDate = up.EndDate
FROM TableB up WHERE up.UserID = (SELECT Id from TableC u where u.Name = TableA.UserName)

Query to update records from two different tables

I have a query that updates table records.
UPDATE #TEMP
SET [fld_LastName] = CustomerProfile.fld_LastName
,fld_FirstName = CustomerProfile.fld_FirstName
,fld_BirthDate = CustomerProfile.fld_BirthDate
FROM [DB_1].[dbo].[tbl_Customer] AS CustomerProfile --c
WHERE CustomerProfile.fld_CustomerNo = #TEMP.fld_CustomerNo
I want to update the records when the customer is not present in:
[DB_1].[dbo].[tbl_Customer]
I would want to look up to:
[DB_2].[dbo].[tbl_Customer]
How can i do that in an SQL Query?
Thanks a lot.
This should work for you:
UPDATE B
SET [fld_LastName] = CustomerProfile.fld_LastName
,fld_FirstName = CustomerProfile.fld_FirstName
,fld_BirthDate = CustomerProfile.fld_BirthDate
FROM [DB_1].[dbo].[tbl_Customer] AS CustomerProfile INNER JOIN #TEMP B
ON CustomerProfile.fld_CustomerNo = B.fld_CustomerNo
WHERE B.[fld_LastName] IS NULL OR B.fld_FirstName IS NULL OR B.fld_BirthDate IS NULL
You can do it with one update. Something like this:
DECLARE #a TABLE (id INT, val INT)
DECLARE #b TABLE (id INT, val INT)
DECLARE #c TABLE (id INT, val INT)
INSERT #a SELECT 1,NULL UNION SELECT 2,NULL UNION SELECT 3,30
INSERT #b SELECT 1,10
INSERT #c SELECT 1,20 UNION SELECT 2,20
SELECT * FROM #a
UPDATE #a
SET val = COALESCE(b.val,c.val,a.val)
FROM #a a
LEFT JOIN
#b b ON a.id=b.id
LEFT JOIN
#c c ON a.id=c.id
SELECT * FROM #a
This assumes that you prefer NOT NULL values from DB_2 to NULL values in DB_1--if those fields are even nullable.
UPDATE #TEMP
SET fld_LastName = COALESCE(b.fld_LastName,c.fld_LastName,a.fld_LastName)
,fld_FirstName = COALESCE(b.fld_FirstName,c.fld_FirstName,a.fld_FirstName)
,fld_BirthDate = COALESCE(b.fld_BirthDate,c.fld_BirthDate,a.fld_BirthDate)
FROM #Temp a
LEFT JOIN
DB_1.dbo.tbl_Customer b ON a.fld_CustomerNo = b.fld_CustomerNo
LEFT JOIN
DB_2.dbo.tbl_Customer c ON a.fld_CustomerNo = c.fld_CustomerNo