This is based on my previous question.
I have the following table
Table1
JobPositionId | JobPositionName
1 | Sound
2 | Lights
3 | Sound
4 | Ground
How can I delete row three (Name = sound, and max position)
Use:
DELETE FROM TABLE t1
JOIN (SELECT x.jobpositionname,
MAX(jobPositonId) AS max_id
FROM TABLE x
GROUP BY x.jobpositionname) t2
WHERE t1.jobPositonId = t2.max_id
AND t1.jobpositionname = t2.jobpositionname
AND t2.jobpositionname = 'Sound'
As I mentioned in your previous question, using this won't trigger a MySQL 1093 error:
DELETE FROM TABLE
WHERE JobPositionId = SELECT x.id
FROM (SELECT MAX(JobPositionId) AS id
FROM TABLE
WHERE JobPositionName = 'Sound') x
DELETE FROM
Table1
WHERE
JobPositionId = (
SELECT
MAX(JobPositionId)
FROM
Table1
WHERE
JobPositionName = 'Sound'
)
Sorry if this doesn't take into account your "previous question" thought I'd just look at this one.
DELETE FROM Table1 WHERE jobpositionid = (SELECT MAX(jobpositionid) FROM table1 WHERE name = 'Sound');
It seems like what you are trying to do is to delete all duplicate JobPositionNames, leaving only the one with the lowest JobPositionId.
I had to do something very similar recently and found the SQL statements getting so complicated, it was much much easier (if much less efficient) to do it in SQL.
So in case this is a poluted database you're trying to clean, just write a script that does this and be done with it (and set some unique indexes to prevent it from happening again).
If this happens all the time, and needs to be done periodicaly, fix the code that does this.
Related
I'm trying to update two columns in MySQL:
update table1
set (table1.score, table1.count) =
(select (table2.maxScore - table2.score ) as diff, count(*)
from table2
where (table2.maxScore - table2.score) <= 600
and table2.age > 50
group by diff);
But, MySQL does not support this syntax. I've seen some examples using JOIN, but I can't make it work here. Many thanks for any help!
Maybe you should SET their values separately,
UPDATE scoresUniverse
SET scoreUniver.GNfemScore = (Analytics.GN_recency_max_score - Analytics.GN_recency_score ),
ScoresUniverse.GNfemCount = (Select count(*) from Analytics.GN_recency_score where (Analytics.PR_recency_max_score - Analytics.PR_recency_score) <= 600 and Analytics.Older_female_50 > 0)
I figured it out! MySQL can definitely update more than one column at once. I needed to change my original query because MySQL requires using JOIN with ON when updating more than one column. To prove it, I added an extra column "secondCol" to my example. I have looked all over the web for this, and never found the answer. I hope this helps some people.
update table1 join
(select (table2.maxScore - table2.score ) as diff, count(*) as count
from table2
where (table2.maxScore - table2.score) <= 600
and table2.age > 50
group by diff) as scores
on table1.count = scores.count
set table1.score = scores.diff, table1.secondCol = scores.count;
I have below query in mysql where I want to check if branch id and year of finance type from branch_master are equal with branch id and year of manager then update status in manager table against branch id in manager
UPDATE manager as m1
SET m1.status = 'Y'
WHERE m1.branch_id IN (
SELECT m2.branch_id FROM manager as m2
WHERE (m2.branch_id,m2.year) IN (
(
SELECT DISTINCT branch_id,year
FROM `branch_master`
WHERE type = 'finance'
)
)
)
but getting error
Table 'm1' is specified twice, both as a target for 'UPDATE' and as a
separate source for data
This is a typical MySQL thing and can usually be circumvented by selecting from the table derived, i.e. instead of
FROM manager AS m2
use
FROM (select * from manager) AS m2
The complete statement:
UPDATE manager
SET status = 'Y'
WHERE branch_id IN
(
select branch_id
FROM (select * from manager) AS m2
WHERE (branch_id, year) IN
(
SELECT branch_id, year
FROM branch_master
WHERE type = 'finance'
)
);
The correct answer is in this SO post.
The problem with here accepted answer is - as was already mentioned multiple times - creating a full copy of the whole table. This is way far from optimal and the most space complex one. The idea is to materialize the subset of data used for update only, so in your case it would be like this:
UPDATE manager as m1
SET m1.status = 'Y'
WHERE m1.branch_id IN (
SELECT * FROM(
SELECT m2.branch_id FROM manager as m2
WHERE (m2.branch_id,m2.year) IN (
SELECT DISTINCT branch_id,year
FROM `branch_master`
WHERE type = 'finance')
) t
)
Basically you just encapsulate your previous source for data query inside of
SELECT * FROM (...) t
Try to use the EXISTS operator:
UPDATE manager as m1
SET m1.status = 'Y'
WHERE EXISTS (SELECT 1
FROM (SELECT m2.branch_id
FROM branch_master AS bm
JOIN manager AS m2
WHERE bm.type = 'finance' AND
bm.branch_id = m2.branch_id AND
bm.year = m2.year) AS t
WHERE t.branch_id = m1.branch_id);
Note: The query uses an additional nesting level, as proposed by #Thorsten, as a means to circumvent the Table is specified twice error.
Demo here
Try :::
UPDATE manager as m1
SET m1.status = 'Y'
WHERE m1.branch_id IN (
(SELECT DISTINCT branch_id
FROM branch_master
WHERE type = 'finance'))
AND m1.year IN ((SELECT DISTINCT year
FROM branch_master
WHERE type = 'finance'))
The problem I had with the accepted answer is that create a copy of the whole table, and for me wasn't an option, I tried to execute it but after several hours I had to cancel it.
A very fast way if you have a huge amount of data is create a temporary table:
Create TMP table
CREATE TEMPORARY TABLE tmp_manager
(branch_id bigint auto_increment primary key,
year datetime null);
Populate TMP table
insert into tmp_manager (branch_id, year)
select branch_id, year
from manager;
Update with join
UPDATE manager as m, tmp_manager as tmp_m
inner JOIN manager as man on tmp_m.branch_id = man.branch_id
SET status = 'Y'
WHERE m.branch_id = tmp_m.branch_id and m.year = tmp_m.year and m.type = 'finance';
This is by far the fastest way:
UPDATE manager m
INNER JOIN branch_master b on m.branch_id=b.branch_id AND m.year=b.year
SET m.status='Y'
WHERE b.type='finance'
Note that if it is a 1:n relationship the SET command will be run more than once. In this case that is no problem. But if you have something like "SET price=price+5" you cannot use this construction.
Maybe not a solution, but some thoughts about why it doesn't work in the first place:
Reading data from a table and also writing data into that same table is somewhat an ill-defined task. In what order should the data be read and written? Should newly written data be considered when reading it back from the same table? MySQL refusing to execute this isn't just because of a limitation, it's because it's not a well-defined task.
The solutions involving SELECT ... FROM (SELECT * FROM table) AS tmp just dump the entire content of a table into a temporary table, which can then be used in any further outer queries, like for example an update query. This forces the order of operations to be: Select everything first into a temporary table and then use that data (instead of the data from the original table) to do the updates.
However if the table involved is large, then this temporary copying is going to be incredibly slow. No indexes will ever speed up SELECT * FROM table.
I might have a slow day today... but isn't the original query identical to this one, which souldn't have any problems?
UPDATE manager as m1
SET m1.status = 'Y'
WHERE (m1.branch_id, m1.year) IN (
SELECT DISTINCT branch_id,year
FROM `branch_master`
WHERE type = 'finance'
)
Modified some stuff from my pic so you guys can understand it
I have this database. I am trying to update a value from a table based on another value from an another table.
I want to update the SUM from salary like this :
( sum = presence * 5 )
This is what I've been trying to use ( unsuccessful )
update table salary
set suma.salary = users.presence * 5
FROM salary INNER JOIN users1 INNER JOIN presence on id_salary = id_presence
I am not sure what to do, I'd appreciate some help, Thanks
In MySQL to UPDATE tables with a join you use this syntax:
UPDATE table1, table2
SET table1.column = some expression
WHERE table1.column = table2.column
That said, even with the updated picture, in your SQL you are mentioning columns that I cannot understand in which table are to be found. You also have an inner join between salariu and users1, with no join condition. Could you please clean up the question and make everything clear?
Assuming you are making the updates to the db structure you were talking about, then you can start working on this one maybe:
UPDATE salary, presence
SET salary.sum = SUM(presence.hours) * 5
WHERE presence.id = salary.id
AND <some filter on the month that depends on salary.date>
Another way, but I'm not sure it is supported in all RDBMS, would be something like this:
UPDATE salary
SET sum = (
SELECT SUM(presence.hours) * 5
FROM user, presence
WHERE presence.id = salary.id
AND <some filter on the month that depends on salary.date>
)
This question already has answers here:
Swapping column values in MySQL
(23 answers)
Closed 8 years ago.
i am wanting to try and run a query which will update my table ptb_messages and switch the data of two columns around, for instance heres my table:
id | to_user_id | from_user_id |
1 4 5
2 5 6
3 7 9
so what i want to try and do is switch the value of from_user_id over to to_user_id and vice versa.
i was going to use this before i realised that once i copied the value from one table to the other the the original data from the other column would then have been overwritten,
$sql = mysql_query("UPDATE ptb_messages SET ptb_messages.from_user_id=ptb_messages.to_user_id");
what i really need is a swap function,
im not really sure how i might do this but im imagining its something like this:
$sql = mysql_query("UPDATE ptb_messages SET to_user_id=from_user_id, from_user_id=to_user_id");
hope someone can help me please.
Well, mysql has a concept called user variable. You can take advantage of this to store the value and set it on the column for swapping,
UPDATE Table1
SET to_user_id = from_user_id,
from_user_id = #r1
WHERE #r1 := to_user_id
see here: http://www.sqlfiddle.com/#!2/8cd6a/1
how about joining the table with itself?
UPDATE Table1 a
INNER JOIN Table1 b
ON a.to_user_id = b.to_user_id AND
a.from_user_id = b.from_user_id
SET a.to_user_id = b.from_user_id,
a.from_user_id = b.to_user_id
see here: http://www.sqlfiddle.com/#!2/d6b4f/1
I'm going to throw an answer out there, although I think Skinny Pipes answer is a little more elegant.
You can create a temporary table to store the values in.
http://www.sqlfiddle.com/#!2/3631d/1
create table ptb_messages_temp (
id int,
tempid int);
insert into ptb_messages_temp (id, tempid) (select id, to_user_id from ptb_messages);
-- DO THE UPDATE
UPDATE ptb_messages
LEFT OUTER JOIN ptb_messages_temp on ptb_messages.id=ptb_messages_temp.id
SET
ptb_messages.to_user_id=ptb_messages.from_user_id,
ptb_messages.from_user_id=ptb_messages_temp.tempid;
Warning: vagueness & unclear questioning will abound because I know squat about databases.
I just discovered that I need to use views as surrogates for a cronned update statement. I can somewhat get the view to work, but I'm having trouble with rows.
This post helped me to bang out the update I need, but now that I know that views can run that update whenever it's needed rather than on a cron schedule, how can I set the view's column value based upon the view's row id or equivalent?
I've got the select I need:
SELECT SUM( table2.column1/ (
SELECT table2constant
FROM table3
)
FROM table2
WHERE table2table1id = table1id
table1id is the AI id column for table1. table2table1id is PKd to table1id. I'd like the view to have a column PKd to table1id like with table2, and the view needs to have every distinct table1id represented.
I'm sure the jargon's way off, but hopefully you can see what I need.
Will provide as many edits as necessary for clarity.
Many thanks in advance!
EDIT1
Should I create a trigger that creates the view upon insert to table1? Just found about materialization which is what I need/want?
Clarity
I need a summed value for each table1.table1id
Progress
With this code, I'm getting the first id from table1 and only the total sum. I need a sum for each table1.id.
CREATE VIEW db1.sums as
SELECT SUM( table2.column1/ (
SELECT table2constant
FROM table3
) as theSum, table1id
FROM table1, table2
WHERE table2.table2table1id = table1.table1id
To be clear I'm still not sure what you're trying to accomplish here but if what you posted works, try
SELECT table1.table1id,
SUM( table2.collumn1 ) / (SELECT table2constant FROM table3 ) as theSum
FROM table1, table2
WHERE table2.table2table1id = table1.table1id GROUP BY table1.table1id
you can replace (SELECT table2constant FROM table3 ) with your constant if it has no reason to otherwise be in the database (if it's not updated)
Its actually very simple. Here is an example of how you can do it.
SELECT SUM( table1.column / table2.column ), table1.*, table2.*
FROM table1, table2
WHERE table1.id = table2.column_id