Mysql help updating rows with same value - mysql

I have a table named status_t:
**id** **page** **status** **locked**_by
1 0 2 0
1 1 2 0
1 2 2 0
2 0 0 0
2 1 2 0
2 2 2 0
primary key is ( id, page) .
In the above example I would like to update all the
rows that all pages have status = 2.
i.e. the query should update all the rows with id = 1 to status 3. So the table will become
**id** **page** **status** **locked**_by
1 0 3 1
1 1 3 1
1 2 3 1
2 0 0 0
2 1 2 0
2 2 2 0
I have tried:
SELECT * FROM status_t AS t
WHERE id IN
(SELECT id FROM status WHERE status = 0) LIMIT 10
the above query fetches the rows to be updated but I cannot do that:
UPDATE status_t as S1 WHERE id IN
(SELECT id FROM status_t WHERE status = 2)
SET S1.status = 3, S1.locked_by = 1
EDIT:
THE ABOVE TABLE IS JUST AN EXAMPLE.
I do not want to update WHERE id = 1 . I just want to update rows no matter the id
that have status = 2 for the same id.
In the above example if the row with key (2, 2) had status = 2 then it should be updated.

This should work:
update status_t t
join (
select distinct id from status_t s
where status=2 and not exists (
select 1 from status_t ss
where s.id=ss.id and s.status <> ss.status
)
) i on i.id = t.id
set t.status = 3
The inner query selects IDs where all values of status are set to 2. It achieves this result by checking that tere are no rows with the same ID and a different status.
Here is a demo on sqlfiddle.

Try this:
UPDATE status_t a
INNER JOIN (SELECT id FROM status_t WHERE STATUS = 2 GROUP BY id HAVING COUNT(*) = 3 LIMIT 1) AS b ON a.id = b.id
SET a.status = 3, a.locked_by = 1;
This will update data as you want for all pages have status = 2

The following should do the trick:
UPDATE status_t
SET status = 3, locked_by = 1
WHERE status = 2
There should be no need to use a sub-query, as the WHERE should be able to be used directly in the UPDATE statement.
EDIT:
I just noticed that you only had an update against the rows with ID = 1, which does not match the statement 'In the above example I would like to update all the rows that all pages have status = 2.. The rows whereid = 2, andstatus = 2` would also be updated by my query.
If you need to only update a particular id, add the following at the end of my query:
AND id = 1

try this
update status_t set staus=3 ,locked_by=1
where id=1
or
update status_t set status=3 ,locked_by=1
where status=2

UPDATE status_t SET status = 3, S1.locked_by = 1 WHERE id = 1

Try this::
UPDATE status_t SET status = 3, locked_by = 1 WHERE status = 2
And if you want to achieve this in your way :
UPDATE
status_t as S1
INNER JOIN
(
SELECT keyword_id
FROM status_t WHERE status = 2
) as tempStatus ON id= tempStatus.keyword_id
SET S1.status = 3, S1.locked_by = 1

Related

MySQL IF function with multiple expressions

I am new to MySQL statements, so bear with me.
I am working with a single table that contains 3 columns.
ID, value, and report ID.
What I am looking to do is update the 'value' to yes of id = 2 WHEN the value is 'yes' for id = 1, and at the same time matching the report id is matching between id 1 and id 2. Apologies if this doesn't make sense, please let me know if I need to clarify better.
Here are some queries I've attempted so far:
UPDATE table
SET value = CASE WHEN value = 'Yes' AND id = 1 AND report_id LIKE report_id
THEN 'Yes' ELSE value END
WHERE (id = 2 or id = 1);
UPDATE table
SET value = 'Yes'
WHERE (report_id = report_id
AND value = 'Yes')
AND id = 1
OR id = 2;
UPDATE table
SET value = IF(value = 'Yes' AND report_id LIKE report_id AND id = 1, 'Yes', '')
WHERE id = 2;
Example Table:
id
value
report_id
1
yes
1001
1
no
1002
1
yes
1003
2
1001
2
1002
3
cat
1001
5
1002
All your conditions are being processed on a single row, not comparing the id=1 rows to the id=2 rows with the same report_id.
You can use a self-join to compare different rows of the table with a relationship.
You don't need CASE, you can select the rows to update using the WHERE conditions.
UPDATE t1
JOIN t2 ON t1.report_id = t2.report_id
SET t1.value = 'yes'
WHERE t1.id = 2 AND t2.id = 1 AND t2.value = 'yes'
If I understood correctly, please try to use something like below to get the result. You need to use the same table in exists condition as well. I hope my answer helps you.
update table t set t.value = 'Yes' where exists ( select 1 from table t1 where
t1.value = 'Yes' and t1.id = 1 and t.report_id = t1.report_id) and t.id = 2;
UPDATE
table a
JOIN table b ON a.report_id = b.report_id
SET
a.value = 'Yes'
WHERE
a.id = 2
AND b.id = 1
AND b.value = 'Yes';

Updating table based on same table with a max value

Have a table data structure like below:
id
regid
docid
archived
1
1000
1
0
2
1000
2
0
3
1000
3
0
4
2000
1
0
5
2000
2
0
6
3000
1
0
7
3000
2
0
8
3000
3
0
9
3000
4
0
What I'm trying to do update the archived column to 1 where the docid is less than the max docid, by each regid group.
So I should end up with id's 3, 5 & 9 not being set to 1
Have tried:
update table t1
join (select max(docid) as maxdocid, regid from table) t2 on t1.docid < t2.maxdocid and t1.regid = t2.regid
set t1.archived = 1
But doesn't work, only does the first regid group.
Here's a solution (in MySQL 8.0+) using a CTE:
WITH numbered_table AS (
SELECT id, ROW_NUMBER() OVER (PARTITION BY regid ORDER BY docid DESC) AS rownum
FROM mytable
)
UPDATE mytable JOIN numbered_table USING (id)
SET archived = 1
WHERE rownum > 1
AND archived = 0;
Second solution, if you use an older version of MySQL that doesn't support CTE syntax:
You don't really need to compute the max docid value. If you want to update all rows except for the row with the max docid value, then you can check if a row can be matched to any other row with a greater docid value.
UPDATE mytable AS t1
INNER JOIN mytable AS t2 ON t1.regid = t2.regid AND t1.docid < t2.docid
SET t1.archived = 1
WHERE t1.archived = 0;
This will be true for all rows except the row with the max value. That row will be excluded automatically by the join.
In steps:
Create a query with the MAX value, per docid:
SELECT
ID,
regid,
docid,
(SELECT MAX(docid) FROM t1 te where te.regid=t.regid) as M
FROM t1 t
Join the result, and update:
UPDATE t1
JOIN (
SELECT
ID,
regid,
docid,
(SELECT MAX(docid) FROM t1 te where te.regid=t.regid) as M
FROM t1 t
) x ON t1.id=x.id
SET archived = 1
WHERE t1.docid<x.M AND t1.archived=0;
see: DBFIDDLE
You could try:
update test_tbl t1
set t1.archived = 1
where t1.archived = 0
and t1.id not in ( select t2.id
from (select max(id) as id,
regid,
max(docid)
from test_tbl
group by regid
) as t2
) ;
Result:
id regid docid archived
1 1000 1 1
2 1000 2 1
3 1000 3 0
4 2000 1 1
5 2000 2 0
6 3000 1 1
7 3000 2 1
8 3000 3 1
9 3000 4 0
Demo
Or you can use a LEFT JOIN
update test_tbl t1
left join ( select max(id) as id,
regid,
max(docid) as docid
from test_tbl
group by regid
) as t2 on t1.id=t2.id
set t1.archived = 1
where t1.archived = 0
and t2.id IS NULL
Demo
Use a self join in the update statement:
UPDATE tablename t1
INNER JOIN tablename t2
ON t2.regid = t1.regid AND t2.docid > t1.docid
SET t1.archived = 1;
See the demo.

UPDATE all, except last

I have a table like this:
table_documents
document_id
document_folder_id
document_title
document_notify_expired
ID FOLDER TITLE Notify Expired
1 2 Test1 1
2 2 Test2 1
3 2 Test3 1
4 2 Test4 1
5 2 Test5 1
I'm like to UPDATE and set document_notify_expired to 0 for all records EXCEPT last, for a specific folder like below
ID FOLDER TITLE Notify Expired
1 2 Test1 0
2 2 Test2 0
3 2 Test3 0
4 2 Test4 0
5 2 Test5 1
Here my code but not update as expected
UPDATE table_documents docs
LEFT OUTER JOIN ( SELECT * FROM table_documents ORDER BY document_id DESC LIMIT 1 )last_doc ON last_doc.document_id = docs.document_id
SET doc.document_notify_expired = '0'
WHERE document_folder_id = '2'
AND last_doc.document_notify_expired = '1'
Try this out
UPDATE table_documents docs
INNER JOIN
(SELECT
MAX(id) id
FROM
table_documents) docsmax ON docs.id != docsmax.id
SET
document_notify_expired = 0;
Obviously the last row has the greatest id, so this row is not going to be there after the join, which will returns all the other rows and you can play with them as you wish.
update table1.table_documents
set table1.document_notify_expired = 0
where table1.document_folder_id = 2
and not table1.document_id = (
select table2.document_id
from table_documents as table2
where table2.document_folder_id = 2
order by table2.document_id desc
limit 1
);

Generate a column with value 1 if first parent_id level > 1 than id level

I want to get all the data from the table, and generate on the fly a column with the value 1 at the parent of the entries with this parent_id. And it should be compatible with "sql server", "postgres", "mysql".
id,parent_id,lft,rgt,level,title,alias,access,path,checked_out
1 0 0 7 0 root root 0 root ...
2 1 1 2 1 ...
Result should be:
id,parent_id,lft,rgt,level,**button**,title,alias,access,path,checked_out
1 0 0 7 0 1 root root 0 root 0...
2 1 1 2 1 **0** ...
Is this ever possible, I´ll never done such a complicated query before.
It should select all table entries, generate a new button column with value 1 or 0, and this only at the parent level of it's entries
Something like this but with a result of all entries:
SELECT a.id,b.id,a.level,a.level+1 as button
FROM `categories` a
JOIN `categories` b ON a.id=b.parent_id
WHERE a.id < b.id AND a.level+1 = b.level AND b.id-a.id=1;
CASE and EXISTS should work in all of these RDBMS:
SELECT id, parent_id, lft, rgt, level
, CASE WHEN EXISTS (
SELECT 1 FROM tbl AS b
WHERE b.parent_id = a.id
AND b.level = a.level + 1
-- AND b.id > a.id -- this one is redundant
AND b.id = a.id + 1)
THEN 1 ELSE 0 END AS button
, ...
FROM tbl AS a;
This returns rows that have any children with button = 1. Else button = 0.

PHP single query Multiple UPDATE effecting AUTO_INCREMENT id instead of order_id

Here is my super-simple table layout...
id | order
1 | 1
2 | 2
I've been trying to update the order for both entries with a single query however my query tests seem to keep updating the auto_increment id field.
My goal is to make id1 = order 2 and id2 = order1 in a single query. What am I doing wrong with my query?
UPDATE forms
SET order = CASE id
WHEN 1 THEN 2
WHEN 2 THEN 1
END
WHERE id IN (1,2);
How about doing JOIN?
UPDATE Tablename AS a
INNER JOIN Tablename AS b
ON a.id = 1 AND b.id = 2
SET a.order = b.order,
b.order = a.order
SQLFiddle Demo