I have 2 tables:
LOGS_TABLE:
FID (NUMBER)
SERIAL_NUMBER (VARCHAR2)
LOG_RESULT (VARCHAR2)
POINT_TABLE:
FID (NUMBER)
SERIAL_NUMBER (VARCHAR2)
FID_LOG (NUMBER)
The attribute to join tables is SERIAL_NUMBER, but what I need is to insert into POINT_TABLE.FID_LOG values from LOGS_TABLE.FID on basement SERIAL_NUMBER relations.
How can I do this?
For Oracle you may use following statement:
UPDATE (SELECT p.FID_LOG fid_log
, l.FID fid
FROM POINT_TABLE p
, LOGS_TABLE l
WHERE p.SERIAL_NUMBER = l.SERIAL_NUMBER)
SET fid_log = fid
Also it is possible to use MERGE statement like this:
MERGE INTO POINT_TABLE p
USING (SELECT *
FROM LOGS_TABLE) l
ON (p.SERIAL_NUMBER = l.SERIAL_NUMBER)
WHEN MATCHED THEN
UPDATE
SET p.FID_LOG = l.FID;
Related
I have two tables, one called whoop_data with fields (id, user_id, date, recovery, sleep, strain)
and another called whoop_user with fields (id, name, average_recovery, average_sleep, average_strain)
I'd like to update the whoop_user average data fields using the whoop_data that is logged. Below are my attempts to do so.
New to SQL - please be kind :)
The code below results in the following table (works as intended):
name
AVG(recovery)
Name2
39.5
Name1
78
Name3
49.5
/*works as intended*/
SELECT name, AVG(recovery) FROM whoop_users JOIN whoop_data
ON whoop_users.id = whoop_data.user_id
GROUP BY name;
Both of the attempts below result in the following table:
Name
average_recovery
Name1
39.5
Name2
39.5
Name3
39.5
I see what is happening, but I don't understand why, how to fix it, or why the statement above DO work as intended and the ones below don't.
/*attempt 1*/
UPDATE whoop_users
SET
average_recovery = (SELECT AVG(recovery)
FROM whoop_users JOIN whoop_data ON
whoop_users.id = whoop_data.user_id
GROUP BY name)
WHERE
EXISTS (
SELECT * FROM whoop_data
WHERE whoop_data.user_id = whoop_users.id );
SELECT * FROM whoop_users;
/*attempt 2*/
WITH a AS
(
SELECT AVG(recovery) as av
FROM whoop_users JOIN whoop_data
ON whoop_users.id = whoop_data.user_id
GROUP BY name
)
UPDATE whoop_users
SET
average_recovery = (SELECT av FROM a);
SELECT * FROM whoop_users;
You must correlate properly the subquery that returns the averages from whoop_data (no joins are needed):
UPDATE whoop_users AS u
SET (average_recovery, average_sleep, average_strain) =
(
SELECT AVG(d.recovery), AVG(d.sleep) avg_sleep, AVG(d.strain)
FROM whoop_data AS d
WHERE d.user_id = u.id
);
If your version of SQLite is 3.33.0+ you could also use the UPDATE...FROM syntax which sometimes performs better:
UPDATE whoop_users AS u
SET average_recovery = d.avg_recovery,
average_sleep = d.avg_sleep,
average_strain = d.avg_strain
FROM (
SELECT user_id,
AVG(recovery) avg_recovery,
AVG(sleep) avg_sleep,
AVG(strain) avg_strain
FROM whoop_data
GROUP BY user_id
) AS d
WHERE u.id = d.user_id;
In Postgres 9.5, I want to connect to another DB using Postgres' dblink, get data and then use them to update another table.
-- connect to another DB, get data from table, put it in a WITH
WITH temp_table AS
(
SELECT r_id, descr, p_id
FROM
dblink('myconnection',
'SELECT
r_id, descr, p_id
FROM table
WHERE table.p_id
IN (10,20);'
)
AS tempTable(r_id integer, descr text, p_id integer)
)
-- now use temp_table to update
UPDATE anothertable
SET
descr =temp_table.descr
FROM anothertable AS x
INNER JOIN temp_table
ON
x.r_id = temp_table.r_id
AND
x.p_id = temp_table.p_id
AND
x.p_id IN (2) ;
dblink works fine and if I do select * from temp_table before the UPDATE, it has data.
The issue is the UPDATE itself. It runs with no errors, but it never actually updates the table.
I tried changing the UPDATE to:
UPDATE anothertable
SET
descr =temp_table.descr
FROM anothertable AS x , temp_table
WHERE x.r_id = temp_table.r_id
AND
x.p_id = temp_table.p_id
AND
x.p_id IN (2) ;
Same as above: runs with no errors, but it never actually updates the table.
I also tried to change the UPDATE to:
UPDATE anothertable
INNER JOIN temp_table
ON x.r_id = temp_table.r_id
AND
x.p_id = temp_table.p_id
AND
x.p_id IN (2)
SET descr =temp_table.descr
But I get:
ERROR: syntax error at or near "INNER" SQL state: 42601
Character: 1894
How can I fix this to actually update?
Don't repeat the target table in the FROM clause of the UPDATE:
WITH temp_table AS ( ... )
UPDATE anothertable x
SET descr = t.descr
FROM temp_table t
WHERE x.r_id = t.r_id
AND x.p_id = t.p_id
AND x.p_id IN (2);
Or simplified:
...
AND x.p_id = 2
AND t.p_id = 2
The manual:
Do not repeat the target table as a from_item unless you intend a self-join (in which case it must appear with an alias in the from_item).
Related:
UPDATE statement with multiple joins in PostgreSQL
SQL update query with substring WHERE clause
I have a table in a database called T_USR which includes the following fields:-
USRUID (Primary Key)
USRID <- This is the current employee ID
I also have a temp table #TEMP3 populated from a CSV file which includes:
USRUID (the value of this field will match the Primary Key in T_USR)
EMPID <- This is to be the new employee ID
#TEMP3 contains only a subset of the users found in T_USR
What i need is a query that will update the value of T_USR.USRID with the value from #TEMP3.EMPID ONLY if the member of staff (USRUID) exists in both tables.
This is the query I wrote, but for users who appear in T_USR and NOT in #TEMP3, the USRID field was set to NULL which is not the required result. For users who do not appear in both tables, I want their details to remain unchanged.
Update dbo.T_USR
SET dbo.T_USR.USRID =
(SELECT dbo.#TEMP3.EMPID
FROM #TEMP3
Where dbo.T_USR.USRUID = dbo.#TEMP3.USRUID
and exists (
select * from #TEMP3 where dbo.T_USR.USRUID = #TEMP3.USRUID)
)
I'd appreciate any suggestions. Thank you.
Use join. If I understand correctly:
update u
set u.usrid = t.empid
from dbo.T_USR u join
#temp3 t
on u.usruid = t.usruid
use this :
UPDATE t
SET USRID = EMPID
FROM #TEMP3 te
JOIN dbo.T_USR t ON t.USRUID = te.USRUID
Use Following Query, it Will update only rows exists on both table.
Update dbo.T_USR
SET dbo.T_USR.USRID =
(SELECT dbo.#TEMP3.EMPID
FROM #TEMP3
Where dbo.T_USR.USRUID = dbo.#TEMP3.USRUID
)
WHERE exists (
select * from #TEMP3 AS TT where dbo.T_USR.USRUID = TT.USRUID)
I have flat table which I have to join using EAN attribute with my main table and update gid (id of my main table).
id attrib value gid
1 weight 10 NULL
1 ean 123123123112 NULL
1 color blue NULL
2 weight 5 NULL
2 ean 331231313123 NULL
I was trying to pivot ean rows into column, next join on ean both tables, and for this moment everything works great.
--update SideTable
--set gid = ab_id
select gid, ab_id
from SideTable
pivot (max (value) for attrib in ([EAN],[MPN])) as b
join MainTable as c
on c.ab_ean = b.EAN
where b.EAN !='' AND c.ab_archive = '0'
When I am selecting both id columns is okey, but when I am uncomment first lines and delete select whole table is set with first gid from my main table.
It have to set my main id into all attributes where ID where ean is matched from my main table.
I am sorry for my terrible english but I hope someone can help me, with that.
The reason your update does not work is that you don't have any link between your source and target for the update, although you reference sidetable in the FROM clause, this is effectively destroyed by the PIVOT function, leaving no link back to the instance of SideTable that you are updating. Since there is no link, all rows are updated with the same value, this will be the last value encountered in the FROM.
This can be demonstrated by running the following:
DECLARE #S TABLE (ID INT, Attrib VARCHAR(50), Value VARCHAR(50), gid INT);
INSERT #S
VALUES
(1, 'weight', '10', NULL), (1, 'ean', '123123123112', NULL), (1, 'color', 'blue', NULL),
(2, 'weight', '5', NULL), (2, 'ean', '331231313123', NULL);
SELECT s.*
FROM #S AS s
PIVOT (MAX(Value) FOR attrib IN ([EAN],[MPN])) AS pvt;
You clearly have a table aliased s in the FROM clause, however because you have used pivot you cannot use SELECT s*, you get the following error:
The column prefix 's' does not match with a table name or alias name used in the query.
You haven't provided sample data for your main table, but I am about 95% certain your PIVOT is not needed, I think you can get your update using just normal JOINs:
UPDATE s
SET gid = ab_id
FROM SideTable AS s
INNER JOIN SideTable AS ean
ON ean.ID = s.ID
AND ean.attrib = 'ean'
INNER JOIN MainTable AS m
ON m.ab_EAN = ean.Value
WHERE m.ab_archive = '0'
AND m.ab_EAN != '';
As per comment to the question, you need to use update + select statement.
A standard version looks like:
UPDATE
T
SET
T.col1 = OT.col1,
T.col2 = OT.col2
FROM
Some_Table T
INNER JOIN
Other_Table OT
ON
T.id = OT.id
WHERE
T.col3 = 'cool'
As to your needs:
update a
set a.gid = p.ab_id
from SideTable As a
Inner join (
select gid, ab_id
from SideTable
pivot (max (value) for attrib in ([EAN],[MPN])) as b
join MainTable as c
on c.ab_ean = b.EAN
where b.EAN !='' AND c.ab_archive = '0') p ON a.ean = p.EAN
try and break it down a bit more like this..
update SideTable
set SideTable.gid = p.ab_id
FROM
(
select gid, ab_id
from SideTable
pivot (max (value) for attrib in ([EAN],[MPN])) as b
join MainTable as c
on c.ab_ean = b.EAN
where b.EAN !='' AND c.ab_archive = '0'
) p
WHERE p.EAN = SideTable.EAN
How would you update data in multiple tables using a single query?
MySQL Example
The equivalent code in MySQL:
UPDATE party p
LEFT JOIN party_name n ON p.party_id = n.party_id
LEFT JOIN party_details d ON p.party_id = d.party_id
LEFT JOIN incident_participant ip ON ip.party_id = p.party_id
LEFT JOIN incident i ON ip.incident_id = i.incident_id
SET
p.employee_id = NULL,
c.em_address = 'x#x.org',
c.ad_postal = 'x',
n.first_name = 'x',
n.last_name = 'x'
WHERE
i.confidential_dt IS NOT NULL
What would be the same statement using Oracle 11g?
Thank you!
RTFM
It seems a single query is insufficient when using Oracle:
http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/statements_108a.htm#2067717
/** XXX CODING HORROR... */
Depending on your needs, you could use an updateable view. You create a view of your base tables and add an "instead of" trigger to this view and you update the view directly.
Some example tables:
create table party (
party_id integer,
employee_id integer
);
create table party_name (
party_id integer,
first_name varchar2(120 char),
last_name varchar2(120 char)
);
insert into party values (1,1000);
insert into party values (2,2000);
insert into party values (3,3000);
insert into party_name values (1,'Kipper','Family');
insert into party_name values (2,'Biff','Family');
insert into party_name values (3,'Chip','Family');
commit;
select * from party_v;
PARTY_ID EMPLOYEE_ID FIRST_NAME LAST_NAME
1 1000 Kipper Family
2 2000 Biff Family
3 3000 Chip Family
... then create an updateable view
create or replace view party_v
as
select
p.party_id,
p.employee_id,
n.first_name,
n.last_name
from
party p left join party_name n on p.party_id = n.party_id;
create or replace trigger trg_party_update
instead of update on party_v
for each row
declare
begin
--
update party
set
party_id = :new.party_id,
employee_id = :new.employee_id
where
party_id = :old.party_id;
--
update party_name
set
party_id = :new.party_id,
first_name = :new.first_name,
last_name = :new.last_name
where
party_id = :old.party_id;
--
end;
/
You can now update the view directly...
update party_v
set
employee_id = 42,
last_name = 'Oxford'
where
party_id = 1;
select * from party_v;
PARTY_ID EMPLOYEE_ID FIRST_NAME LAST_NAME
1 42 Kipper Oxford
2 2000 Biff Family
3 3000 Chip Family
I was having the same problem I couldn't find a easy way to do this in Oracle.
Look here:
Oracle Update Statements for more info.
You could use Oracle MERGE statement to do this. It is a bulk update-or-insert kind of statement based on joining the target table with an inline view.
MERGE INTO bonuses D
USING (
SELECT employee_id, salary, department_id FROM employees
WHERE department_id = 80
) S ON (D.employee_id = S.employee_id)
WHEN MATCHED THEN
UPDATE SET D.bonus = D.bonus + S.salary*.01
WHEN NOT MATCHED THEN
INSERT (D.employee_id, D.bonus)
VALUES (S.employee_id, S.salary*0.1);
if you do not need the insert part, you just omit the last 3 lines above.
In some cases it's possible to use PL/SQL to achieve this. In my case I searched for matching rows in two tables by some criteria, then updated each row in a loop.
Something like this:
begin
for r in (
select t1.id as t1_id, t2.id as t2_id
from t1, t2
where ...
) loop
update t1
set ...
where t1.id = r.t1_id;
update t2
set ...
where t2.id = r.t2_id;
end loop;
end;