Set column status based on a match between two tables - sql-server

I have two tables
T1
id
1
2
3
4
T2
id status
1 Yes
2 Yes
3 Yes
4 Yes
5 No
6 No
If I find id matched in both the tables, the status should be updated as Yes else No

One method is to use a CASE expression and EXITS with a correlated subquery that checks for the existence of a row in the other table.
UPDATE t2
SET status = CASE
WHEN EXISTS (SELECT *
FROM t1
WHERE t1.id = t2.id) THEN
'Yes'
ELSE
'No'
END;

You can update using a LEFT JOIN. If the t1.id is null, then there is no match, and you can set it to No. Otherwise, set it to yes.
UPDATE t2
SET t2.Status = CASE WHEN t1.id IS NOT NULL THEN 'Yes'
ELSE 'No'
END
FROM t2
LEFT JOIN t1
ON t1.id = t2.id
Alternatively, you can use a subquery within the CASE
UPDATE t2
SET t2.Status = CASE WHEN t2.id IN (SELECT id FROM t1) THEN 'Yes'
ELSE 'No'
END

Related

Find matched column records in one table that may be in multiple columns in a second table

I have two tables, Table 1 with multiple columns, name, ID number, address, etc. And Table 2 with columns, ID number 1 and ID number 2 and a few other columns.
I am trying to get a T-SQL query returning all rows in Table 1 with an indicator showing whether the ID number in Table 1 matches either ID_1 or ID_2 in Table 2. The result set would be all columns from Table 1 , plus the indicator “Matched” if the ID number in Table 1 matches either ID_1 or ID_2 in Table 2.
Table 1: ID | Name | Address |
Table 2: ID_1 | ID_2
Result
T1.ID, Name, Address, ("Matched"/"Unmatched") ...
Also, would it be the same to do the opposite, meaning instead of the result including all rows from Table 1 that have a matching ID in ID_1 or ID_2 in Table 2, the result set would include only records from Table 1 where t1.ID = (T2.ID_1 or T2.ID_2)?
SELECT DISTINCT
CASE
WHEN (table1.ID = table2.ID_1 )
THEN 'Matched'
ELSE 'Unmatched'
END AS Status ,
table1.*
FROM
table1
LEFT JOIN
table2 ON table1.ID = table2.ID_1
UNION
SELECT DISTINCT
CASE
WHEN (table1.ID = table2.ID_2)
THEN 'Matched'
ELSE 'Unmatched'
END AS Status,
table1.*
FROM
table1
LEFT JOIN
table2 ON table1.ID = table2.ID_2
I think that a correlated subquery with an exists condition would be a reasonable solution:
select
t1.*,
case when exists (select 1 from table2 t2 where t1.id in (t2.id_1, t2.id_2))
then 'Matched'
else 'Unmatched'
end matched
from table1 t1
And the other way around:
select
t2.*,
case when exists (select 1 from table1 t1 where t1.id in (t2.id_1, t2.id_2))
then 'Matched'
else 'Unmatched'
end matched
from table2 t2
If you want to "align" the rows based on the match for the whole dataset at once, then you might want to try a full join:
select t1.*, t2.*
from table1 t1
full join table2 t2 on t1.id in (t2.id_1, t2.id_2)

Update using case with multiple tables

I have two tables. I want to update table1 when the condition is satisfied. The condition here is to check the country in table 2 and if its Mex, then multiply rate i.e. 0.5 to the price.
I wrote the following code
UPDATE table1
SET table1.Price = (SELECT *,
CASE table2.Country
WHEN 'CANADA' THEN (1 * table2.price)
WHEN 'MEXICO' THEN (0.5 * table2.price)
ELSE 0
END AS Price_Calc
FROM table2)
FROM table1;
As I run this it gives the below error
Msg 116, Level 16, State 1, Line 12 Only one expression can be
specified in the select list when the subquery is not introduced with
EXISTS.
Try Like below
UPDATE t1
SET t1.table1.Price = (SELECT
CASE t2.Country
WHEN 'CANADA' THEN (1 * t2.price)
WHEN 'MEXICO' THEN (0.5 * t2.price)
ELSE 0
END AS Price_Calc
FROM table2 t2
WHERE t2.Id = t1.Id -- Here it is suggestion to update target
-- column based on relation if exists between
-- ur tables
)
FROM table1 t1;
Assuming Table1 and Table2 are related through IDs:
UPDATE t1 SET t1.Price = t2.Price
* CASE t2.Country
WHEN 'CANADA' THEN 1.
WHEN 'MEXICO' THEN .5
ELSE 0
END
FROM table1 t1
INNER JOIN table2 t2 ON t2.Id = t1.Id
;

SQL Server : Left Join using 1 = 1

My application is developed using framework so I need to follow some structure which can't be changed.
In SQL Server, I need to achieve inner join using left join which is possible using 1=1
Now in my case there is an Account table with few details, and account_ext table with a few more columns of account related information.
There is an ACCT_NAME_LNK table which has link to particular name to particular account and it has expiry date also
Now I need to fetch all records which has link to name link table and acct table
My conditions is it should not show expired records and in or condition T2.AcctHDDescription like '6%'
This means there should be link to name or ACCTHDDescription should like '6%'
So it should not show expired record but it is showing
Below is my query
DECLARE #EXPDATE DATETIME
SET #EXPDATE = GETDATE()
SELECT DISTINCT
T1.ID, T1.AccountID, T2.AcctHDDescription
FROM
ACCT T1
LEFT JOIN
ACCT_Ext T2 ON T1.ID = T2.ID
LEFT JOIN
ACCT_NAME_LNK T3 ON 1 = 1
AND ISNULL(T3.EXPIRED, '2999-12-31') > #EXPDATE
WHERE
T1.ID = T3.acctid OR T2.AcctHDDescription LIKE '6%'
Added one more image with more details
I need to achieve the output using left join on 1=1
And it has Or condition
[{Link available and not expired} or {AcctHDDescription = '6%'}]
Latest Image which shows output
Expected output
Id AccountId AcctHDDDescription
3 33333 1234
4 62343 345
6 624323 6667
That is a bit of a strange query but I think your issue lies in the WHERE clause OR condition. My initial guess is you want to move the ID join into the left join:
declare #EXPDATE datetime
set #EXPDATE=GETDATE()
SELECT DISTINCT T1.ID,T1.AccountID ,T2.AcctHDDescription
FROM ACCT T1 LEFT JOIN ACCT_Ext T2 ON T1.ID = T2.ID
LEFT JOIN ACCT_NAME_LNK T3 ON 1 = 1
AND ISNULL( T3.EXPIRED, '2999-12-31' ) > #EXPDATE
AND T1.ID = T3.acctid
where T2.AcctHDDescription like '6%'
Just guessing what you want,
DECLARE #EXPDATE DATETIME
SET #EXPDATE=GETDATE();
SELECT T1.ID
, T1.AccountID
, T2.AcctHDDescription
, T3.Expired
FROM Acct T1
LEFT JOIN Acct_Ext T2
ON T1.ID = T2.ID
LEFT JOIN ACCT_NAME_LNK T3
ON T1.ID = T3.acctid
WHERE (T2.AcctHDDescription like '6%' AND ISNULL(T3.EXPIRED, '2999-12-31' ) > #EXPDATE)
OR ISNULL( T3.EXPIRED, '2999-12-31' ) > #EXPDATE;

SQL Server stored procedure select, exists, multiple tables

Any method to do this?
Table1
1
2
3
4
5
Table2
3 (with the condition)
4 (without the condition)
I want to:
Select all records from Table1 if it exists in Table 2, where...(condition)
Select all records from Table1 if it not exists in Table2
Combine both select results. Sort all results with their created date.
For example, the result should be:
Result
1
2
3
5
Hopefully this can help.
SELECT t1.* from table1 t1
JOIN table2 t2
ON t1.ID = t2.ID
UNION ALL
SELECT t1.* from table1 t1 where ID in
(
SELECT t2.ID from table1 t1 except Select t2.ID from table2 t2
)
ORDER BY t1.CreatedDate
You can achieve this by doing:
SELECT t1.id
FROM Table1 t1
LEFT JOIN Table2 t2 on t1.id = t2.id
WHERE condition OR t2.id IS NULL
ORDER BY t1.CreatedDate;
See fiddle (I assumed condition to be t2.id!=4, but it can be anything else depending on other data in your tables).
There could be multiple solution.
One way
we can get the result set using two different queries and at last combine both of the result-set using UNION
Another way,
First statement is saying that get all the result set from TABLE1 if it exists in TABLE2 as well with some criteria (condition in where clause)
means using INNER JOIN we can achieve this
Second statement is saying get all the result set from TABLE1 which are not present in TABLE2
means along with INNER JOIN ed query also include the TABLE1's data if not present in TABLE2
here we can take the help of LEFT OUTER JOIN (taking TABLE1 on the left side)
Assumption: (condition: t1.Id != 4)
Let's try to understand the query using both of the above mentioned ways
---- -- --Step1 Create table and insert records
---- create table1 with Id int identity columsn
--CREATE TABLE Table1 (Id INT IDENTITY(1,1), CreatedDate smalldatetime default(getdate()));
--go
---- insert 1st 5 integers into Table1
--INSERT INTO Table1 DEFAULT VALUES
--go 5
---- create Table2 with Id int column
--CREATE TABLE Table2 (Id INT , CreatedDate smalldatetime default(getdate()));
--go
---- insert records 3,5 into Table2
--INSERT INTO Table2(Id) VALUES (3), (4);
-- -- -- Solution: one way
; WITH cteMyFirstResult AS
(
-- 2.1. Select all records from Table1 if it exists in Table 2, where...(condition)
SELECT
Id, CreatedDate
FROM Table1 AS t1
WHERE t1.Id IN (SELECT Id FROM Table2 AS t2)
AND t1.Id != 4 -- assumption it can be any condition
),cteMySecondResult AS (
-- 2.2. Select all records from Table1 if it not exists in Table2
SELECT
Id, CreatedDate
FROM Table1 AS t1 WHERE t1.Id NOT IN (SELECT Id FROM Table2 AS t2)
)
-- 2.3. Combine both select results. Sort all results with their created date.
SELECT
Id, CreatedDate
FROM cteMyFirstResult
UNION
SELECT
Id, CreatedDate
FROM cteMySecondResult
ORDER BY CreatedDate;
-- -- Solution: Another way (with bug)
SELECT t1.Id, t1.CreatedDate
FROM Table1 AS t1
LEFT JOIN Table2 AS t2 on t1.id = t2.id
WHERE t1.Id != 4
Order by T1.CreatedDate;
-- in this query we are using the criteria after doing the join operation.
-- thus after filtering out the result set based on JOIN Condition this condition will get applied
-- and if there is any null record in the Table1 for column Id (used in join) will not come in the final result-set
-- to avoid this we can include NULL check along with our criteria
-- -- Solution: Another way
SELECT t1.Id, t1.CreatedDate
FROM Table1 AS t1
LEFT JOIN Table2 AS t2 on t1.id = t2.id
WHERE ( t1.Id != 4 ) OR t1.Id IS NULL -- include all your criteria within small-barcket)
Order by T1.CreatedDate;
Thanks for all responses.
I come out with the answer I want:
SELECT *
FROM Table1 t1
WHERE NOT EXISTS(SELECT 1 FROM Table2 t2
WHERE t1.ID = t2.ID
AND t2.CIF_KEY = #CifKey
AND t2.STATUS <> ''3'')
AND (condition in where clause)

Using Joins to get all data from left table

I have two tables as shown below.
Id Name Id Status
-------- -------------------
1 A 1 Approved
2 B 6 Approved
3 C 4 Pending
4 D 1 Approved
5 E 1 Pending
6 F 3 Pending
5 Rejected
Now this is how I want the output to be:
Id Name Status
-------------------
1 A Pending
2 B
3 C Pending
4 D Pending
5 E
6 F
I have tried using left join but I am getting multiple rows.
select t1.ID,Name,Status from t1 left join t2 on t1.id=t2.id
and if I add where Status=pending i am getting only ids 1 and 3.
Here are the queries i tried:
select distinct t1.id,name,status from t1 left join t2 on t1.id=t2.id (this gives me duplicate records i.e id 1 is occurs twice with approved and pending)
and also
select distinct t1.id,name,status from t1 left join t2 on t1.id=t2.id where t2.status='pending' (gives me only 1,3 and 4)
Could any one help me,
Thanks in advance.
To include all rows from T1 and only those from T2 with status = 'pending' move the condition into the ON clause SQL Fiddle
SELECT t1.ID,
Name,
Status
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
AND t2.status = 'pending'
To only return one row per id in the event of dupes you could do (Fiddle)
WITH CTE AS
(
SELECT DISTINCT id, Status
FROM T2
WHERE Status = 'Approved'
)
SELECT t1.ID,
Name,
Status
FROM t1
LEFT JOIN CTE
ON t1.id = CTE.id

Resources