I have a two tables i need to copy from table 2 to table 1.
I want the table 1. column departure to be updated on the matching in table 2.
Condition
The table 2 have multiple items for the table 1,( table 1 have many relation with table 2). So in that case i need to sort it by RotationOrder and takes first row.
Table 1
Id Code Departure
479 JJ1256 NULL
480 SR1255 NULL
481 PFOBLEM NULL
482 SO1301 NULL
483 TS1302 NULL
484 YB1305 NULL
485 CU1303 NULL
Table 2
Id Departure RotationOrder CanLoad
479 NULL 1 1
480 NULL 1 2 1
481 NULL 1 3 1
482 NULL 1 4
482 NULL 3
482 NULL 2
482 NULL 4
483 2013-01-21 1 1
483 NULL 3
483 NULL 4
483 NULL 6
What i have tried
UPDATE table1 set Departure = (select top 1 table2.Departure from table2
INNER JOIN table1 on table1.Id = table2.Id where CanLoad =1 order by
RotationOrder )
FROM TABLE1 INNER JOIN TABLE2
ON TABLE1.Id = TABLE2.Id
Problem
This query copy first null value from the table2 and paste it on table1. which is incorrect.
Cross apply top 1, beloved classic:
UPDATE t1 set Departure = q.Departure
FROM table1 t1
cross apply
(
SELECT TOP 1 Departure
FROM table2
WHERE t1.Id=table2.Id
ORDER BY RotationOrder asc
)q
This is the way you'll want to do it:
UPDATE T1
SET Departure = T2.Departure
FROM Table1 T1
CROSS APPLY (SELECT ca.*
FROM Table2 ca
WHERE T1.Id = ca.Id
ORDER BY ca.RotationOrder) T2;
Notice the use of the table's alias in the UPDATE clause. If you use the table's actual name (not it's alias) you are technically declaring a 2nd Table1, which can/does produce odd behavior as it technically creates Cartesian product. It's therefore very important to use the syntax UPDATE [Table Alias] when using the FROM clause in an UPDATE statement.
Ignore null value rows. This assumes you have one non null row per Id
UPDATE Table1 set Departure = Table2.departure
FROM TABLE1 INNER JOIN TABLE2
ON TABLE1.Id = TABLE2.Id where Table2.canload =1 and Table2.deprture is not null
Related
I have two tables, Table1 and Table2 which have in common two fields EmployeeId and ProjectId
Table1
EmployeeId
ProjectId
1
111
2
222
3
333
4
444
Table2
ProjectId
EmployeeId
222
5
111
1
444
4
333
2
555
8
I want to write a query that creates a column called 'Match' indicating whether an EmployeeId/ProjectId combo that appears in Table1 also appears in Table2. For example the first and fourth rows of Table1 should be indicated as matches since those combos appear in Table2 The final output should look like the following :
EmployeeId
ProjectId
Match
1
111
yes
2
222
no
3
333
no
4
444
yes
If anyone knows how to write this sort of query, I would really appreciate the help.
You need a left join on the field of employeeId and ProjectId.
So you will use table1 as the left table, and join table2 as the right table. Then where table2 fails to join, you will get NULL and you can write NO for the match...
SELECT
t1.employeeId,
t1.projectId,
CASE
WHEN t2.employeeId IS NULL THEN 'no' ELSE 'yes'
END AS match
FROM
table1 AS t1
LEFT JOIN
table2 AS t2
ON t2.employeeId = t1.employeeId
AND t2.projectId = t2.projectId
The left table, table1, will serve as the 'permanent' data that populates in the results-set, ie. you will get the whole table (t1) in the output.
The right table, table2, will only join, when there is a condition that employeeId matches AND projectId matches.
Because we choose a left join, the records from t1 that don't have a match in t2 will result in NULL from t2.
i have to similar tables table 1 and table 2 .I want to compare the 2 tables and show the rows that ID is the same but has a different value in another column.
table 1
ID
ACTIVE
100
1
221
1
341
1
and
table 2
ID
ACTIVE
100
1
221
0
341
1
the output should be like this:
ID
ACTIVE
221
1
select t1.*
from t1
join t2 on t1.id = t2.id
where t1.active <> t2.active
I'm looking to left join a value from a subset of data from another table, based on a specific value from the first table. Here are example tables:
table1
-----------------
key date
1 2020-01-02
2 2020-03-02
table2
-----------------
key date value
1 2019-12-13 a
1 2019-12-29 b
1 2020-01-14 c
1 2020-02-02 d
2 2019-11-01 e
2 2019-12-02 f
2 2020-04-29 g
Based on the value of date for a specific key value from table1, I want to select the most recent (MAX(date)) from table2, where temp contains all rows for that key value where date is on or before the date from table1.
So, the resulting table would look like this:
key date value
1 2020-01-02 b
2 2020-03-02 f
I'm thinking I could use some type of logic that would create temp tables for each key value where temp.date <= table1.date, then select MAX(temp.date) from the temp table and left join the value. For example, the temp table for key = 1 would be:
date value
1 2019-12-13 a
1 2019-12-29 b
Then it would left join the value b for key = 1, since MAX(date) = 2019-12-29. I'm not sure if this is the right logic to go about my problem; any help would be greatly appreciated!
You can use a correlated subquery:
select t1.*,
(select t2.value
from table2 t2
where t2.key = t1.key and t2.date <= t1.date
order by t2.date desc
fetch first 1 row only
) as value
from table1 t1;
Note that not all databases support the standard fetch first clause. You may need to use limit or select top (1) or something else depending on your database.
I have to tables :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 1 10/01/2015
4 0 12/02/2015
5 null null
Table2
--------------------------------
ID VAL2 DATE1
--------------------------------
1 N 02/06/2015
1 N 01/08/2015
2 null null
3 O 05/04/2016
3 O 02/02/2015
4 O 01/07/2015
5 O 03/02/2015
5 N 10/01/2014
5 O 12/04/2015
I want to update :
column VAL1 (of Table1) with '0', if VAL2 (of Table2) is equal to 'O'
column DATE1 (of Table1) with the earliest DATE2 (of Table2) for each ID (here my problem)
(This two tables are not so simple, it's just for illustration, they can be joined with the ID column).
Here my code :
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2) --To take the first DATE for each ID where VAL2='O' (not working fine)
FROM Table2 t2, Table1 t1
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Table2 = 'O')
AND VAL1<>'0'; --(for doing the update only if VAL1 not already equal to 0)
The expected result is :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 10/01/2014
The result I get is :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 10/01/2014
4 0 10/01/2014
5 0 10/01/2014
My problem is that the DATE1 is always updated with the same date, regardless of the ID.
You shouldn't have a second reference to table1 in the first subquery; that is losing the correlation between the subquery and the outer query. If you run the subquery on its own it will always find the lowest date in table2 for any ID that has val2='O' in table1, which is 10/01/2014. (Except your sample data isn't consistent; that's actually N so won't be considered - your current and expected results don't match the data you showed, but you said it isn't real). Every row eligible to be updated runs that same subquery and gets that same value.
You need to maintain the correlation between the outer query and the subquery, so the subquery should use the outer table1 for its join, just like the second subquery already does:
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2)
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Val2 = 'O')
AND VAL1<>'0';
You can use this UPDATE statement.
UPDATE TABLE1 T1
SET T1.VAL1 = '0',
T1.DATE1 = (SELECT MIN(T2.DATE2)
FROM TABLE2 T2
WHERE TRIM(T2.ID) = TRIM(T1.ID)
AND T2.VAL2='O')
WHERE T1.ID IN (SELECT T2.ID FROM TABLE2 T2 WHERE T2.VAL2='O')
Hope it will help you.
MYSQL Solution
Hope this MySql syntax also works with ORACLE.
The issue with the SQL is that it only consider the records with VAL2=='O' when calculating the earliest date. So the last record have the date as shown in table below. Record "5 N 10/01/2014" is not considered.
UPDATE Table1, (SELECT * FROM (SELECT * FROM table2 WHERE VAL2='O' ORDER BY ID, DATE1) X GROUP BY X.ID) T2
SET Table1.DATE1=T2.DATE1, Table1.VAL1=0
WHERE Table1.ID=T2.ID
..
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 **03/02/2015**
Tested on MySql 5.6.14
I have a table that contains the following columns:
ID
Master ID
The Master ID can be shared between different rows with different IDs.
E.g.:
ID | Master ID
1 | 1
2 | 1
3 | 1
4 | 2
Knowing the ID I want to retrieve all the rows that share the same master ID
I managed to do it using this query:
Select *
FROM table t
LEFT JOIN table t2
ON t.MASTER_ID = t2.MASTER_ID
Where t.ID = '1'
Then I also tried using:
Select *
FROM table t
LEFT JOIN table t2
ON t.MASTER_ID = t2.MASTER_ID and t.ID = '1'
In that case, it was much slower. Can anyone explain why?
The queries are doing different things, the first you are saying:
1. give me all rows from `table` where `id = 1`
2. Also give me rows from t2 with a matching master ID
In the second you are saying
1. Give me all rows from `table`
2. Return rows from `t2` with a matching master ID and where `t1.ID = 1`
In a simple example you might have
ID Master_ID
------------------------
1 1
2 1
3 1
4 2
So your first query will return:
t1.ID t1.Master_ID t2.ID t2.Master_ID
--------------------------------------------
1 1 1 1
1 1 2 1
1 1 3 1
Your second query will return
t1.ID t1.Master_ID t2.ID t2.Master_ID
--------------------------------------------
1 1 1 1
1 1 2 1
1 1 3 1
2 1 NULL NULL
3 1 NULL NULL
4 2 NULL NULL
So basically in the first query you are returning a limited number of rows from your table, whereas in the second you return all rows, but only join to some of them.
If the t.ID = '1' condition is in the WHERE clause the t.ID='1' condition only has to be evaluated for the number of rows in t. If the t.ID='1' condition is put into the ON clause for the join it must be evaluated for all rows in t2. If there are a lot of rows in t2 this can significantly increase the run time of the query.
You shouldn't include t.ID = '1' in JOIN ON condition since it's not the joined table. condition on the table in FROM part should stay in WHERE clause; whereas condition belongs to joined table should be moved to join on clause so to get a proper outer join effect rather a inner join effect.
You don't need an OUTER JOIN. The reason is simple, your are joining the same table on the same column - there can't be a non-match!
The query to use is therefore
Select *
FROM T
INNER JOIN T t2
ON T.MasterID = t2.MasterID
Where t.ID = 1