Combining two tables with some matching IDs but not all - sql

So I have two tables. Both tables have some matching IDs but not all IDs are in each table. I need to be able to combine the two. Example down below:
Table 1
Name Money ID
Bob 500 1
Nick 600 2
Kim 575 3
Table 2
Name Fees ID
Bob 200 1
Nick 250 2
Ian 100 4
OUTPUT
Name Money Fees ID
Bob 500 200 1
Nick 600 250 2
Kim 575 3
Ian 100 4

This is a simple full outer join with some coalesce to keep the values in a single column:
select coalesce(tbl1.[Name], tbl2.[Name]) [Name]
, tbl1.[Money]
, tbl2.Fees
, coalesce(tbl1.ID, tbl2.ID) ID
from tbl1
full outer join tbl2
on tbl1.ID = tbl2.ID
order by ID

Related

How to write SQL to select a value in table B if not exists in table A otherwise select value in table A?

I want to get a default rate for activity or an override rate if one exists in another table. How can I write SQL for this?
I have this query but it produces an error "every derived table must have its own alias".
select A.id, rate from (
select
A.id, coalesce(B.rate, A.rate) as rate
from
A
left join B on B.id = A.id
);
Consider the following data
table user
user_id name
1 johnny
2 sam
table activity_types
activity_type_id description rate
1 cook steak $12.00
2 flip burgers $9.00
3 wait tables $8.00
4 wash dishes $8.00
table personal_override_rates
user_id activity_type_id rate
1 1 $18
table activities
activity_id user_id activity_type_id qty
1 1 1 1
2 1 2 1
3 2 1 1
4 2 2 1
desired result:
johnny cook steak 1 $18.00
johnny flip burgers 1 $9.00
sam cook steak 1 $12.00
sam flip burgers 1 $9.00
The error you get is because you have a derived table without an alias. You must provide one and then select the id and rate using the alias.
Like this:
select derived_table.id, derived_table.rate from (
select
A.id, coalesce(B.rate, A.rate) as rate
from
A
left join B on B.id = A.id
) as derived_table;

SQL select with three tables and foreign keys

I have three tables :
field:
f_id
f_start
f_end
1
10
20
2
15
25
3
5
10
person :
p_id
p_name
1
Roger
2
John
3
Alicia
affect :
id
fk_field
fk_person
1
2
1
2
1
2
3
3
3
And I would like to select the dates and the names associated to. Like this
p_name
f_start
f_end
Roger
15
25
John
10
20
Alicia
5
10
I'm new to SQL and I don't know if i have to use JOIN or not... Thanks
You must join all 3 tables on their related columns:
SELECT p.p_name, f.f_start, f.f_end
FROM person p
INNER JOIN affect a ON a.fk_person = p.p_id
INNER JOIN field f ON f.f_id = a.fk_field;
Depending on your requirement you may need LEFT instead of INNER joins, but for this sample data the INNER joins will do.

Select from table 1 unless there is a relationship in 2 other tables

I need to query a name(s) from the Officials table, but exclude that name if the person has the day blocked.
For example, if Sam has blocked 8/21/2021 and 9/11/2021, he should not be selected if the corresponding dates are selected from the Games table. Sam should show up if 9/18/2021 is selected, however. I have 3 tables:
Officials tbl
RefId Name
---------------------
1 Jack
2 Sam
3 Jane
Games tbl Blocks tbl
GameId GameDate BlockId RefId BlockDate
------------------------- ----------------------
1 8/21/2021 1 2 8/21/2021
2 9/11/2021 2 2 9/11/2021
3 9/18/2021 3 3 8/21/2021
Desired Output
----------------------------------
If Game 1 is selected: Jack
If Game 2 is selected: Jack and Jane
If Game 3 is selected: Jack, Sam and Jane
The only 2 tables that are related are the Officials table and Blocks table, with the RefId. I need to compare the BlockDate of Blocks table to GameDate of Games table. I have tried some sql language and this below is obviously not correct, but I'm looking for a way to accomplish what I want to do:
#GameDate datetime,
Select c.Id, c.Name
From Officials c
Where In c.Id And Blocks.BlockDate <> Games.GameDate)
You can do it with NOT EXISTS:
SELECT o.*
FROM Officials o
WHERE NOT EXISTS (
SELECT 1
FROM Blocks b INNER JOIN Games g
ON g.GameDate = b.BlockDate
WHERE b.RefId = o.RefId AND g.GameId = ?
);
See the demo.

Update rows in a table based on grouping

I have a table with records of the same type with ID's and a grouping. I need to update the id's of table 1 into table 2 based on the record id from largest to smallest using the position.
Table 1
ID
Group
Name
1
A
Apple
2
A
Apple
3
B
Apple
4
B
Apple
Table 2
ID
recordid
position
group
1
1
250
A
2
2
350
A
3
null
450
A
4
null
550
A
5
3
250
B
6
4
350
B
7
null
450
B
8
null
550
B
update table2
set recordid=T1.ID
From Table1 T1
join Table2 T2 on T2.Group=T1.Group
This isn't distinct so I don't think it's right, but I can't figure it out.
where ?????
the problem is you have multiple Id per group , so you have to choose one :
update table2
set recordid= ( select top 1 T1.ID
From Table1 T1
join Table2 T2 on T2.Group=T1.Group
)
where recordid is null

How to find out which column value changed in SQL

I have two tables with 100 of columns, and I want to find out how which column value changed in those two tables. I can find which row has changed but I want to which column was changed not the whole row.
Table 1
name ID Dept Email EmpID Salary Gender
Rob 1 IT I#i.com 100 5000 M
Mary 2 HR M#m.com 20 6000 F
Jack 3 IT J#j.com 30 7000 M
Harry 4 Fin h#h.com 50 5000 M
Jay 5 Eng Null 60 5000 M
Ken 6 HR K#K.com 70 Null M
Table 2
name ID Dept Email EmpID Salary Gender
Rob 1 IT I#i.com 100 5000 M
Mary 2 HR M#m.com 20 6000 F
Jack 3 IT J#j.com 150 7000 M
Harry 4 Fin h#h.com 50 Null M
Jay 5 Eng Jy#jy.com 60 5000 M
Ken 6 HR K#K.com 70 6000 M
As we can see Email for Jay existed, Emp ID for Jack was changed, Salary for Harry is null in Table 2 and Salary was added for Ken.
Expected Output (If this is possible, As I don't want to see all the row values, I just want to see which column value changed, as ID is a unique identifier, I would like to know which ID did column value change)
ID columnvaluechanged
3 EmpID
4 Salary
5 Email
6 Salary
Here is one way using unpivot technique
;WITH tab1
AS (SELECT id,
colName,
value
FROM Yourtable1
CROSS apply (VALUES (NAME,'name'),(Dept,'Dept'),(Email,'Email'),
(Cast(EmpID AS VARCHAR(50)),'EmpID'),
(Cast(Salary AS VARCHAR(50)),'Salary'),
(Gender,'Gender')) cs (value, colName)),
tab2
AS (SELECT id,
colName,
value
FROM Yourtable2
CROSS apply (VALUES (NAME,'name'),(Dept,'Dept'),(Email,'Email'),
(Cast(EmpID AS VARCHAR(50)),'EmpID'),
(Cast(Salary AS VARCHAR(50)),'Salary'),
(Gender,'Gender')) cs (value, colName))
SELECT t1.ID,
t1.colName,
t1.value AS tab1_value,
t2.value AS tab2_value
FROM tab1 t1
INNER JOIN tab2 t2
ON t1.ID = t2.ID
AND t1.colName = t2.colName
AND Isnull(t1.value, '') <> Isnull(t2.value, '')
Demo