Update same table with IF ELSE Condition in MySQL - mysql

I am trying to update the user_status filed with condition:
update pm_users
set user_status = if (
(select u.user_status from pm_users u where u.user_id = 3
) = '1', '0', '1' )
where user_id = 3
means if user_status = 1 then update the status with 0 and if user status is 0 then with 1.
I am getting the error: You can't specify target table 'pm_users' for update in FROM clause
I think it means i can't use this query like above for the same table? I am not sure.
Please help me to move on the right way, and make me correct.

try the following
update pm_users
set user_status = case when user_status = 0 then 1 else 0 end
where user_id = 3

Rather then maybe try CASE
update pm_users
set user_status = CASE WHEN user_status = '1' THEN '0' ELSE '1' END
WHERE user_id = 3
SQL Fiddle DEMO

Related

MYSQL SELECT is slow when crossing multiple tables

I have a mysql query which is to return the only 1 record that need to cross multiple table. However, the mysql query is slow when executing.
Query:
SELECT *,
(SELECT TreeName FROM sys_tree WHERE TreeId = Mktg_Unit_Booking.ProjectLevelId) AS PhaseName,
(CASE WHEN ProductType = 'U' THEN (SELECT UnitNo FROM prop_unit pu WHERE pu.UnitId = mktg_unit_booking.UnitId)
ELSE (SELECT BayNo FROM prop_car_park pcp WHERE pcp.CarParkId = UnitId) END) AS UnitNo,
(SELECT CustomerName FROM mktg_customer mc WHERE mc.CustomerId = mktg_unit_booking.CustomerId) AS CustomerName
FROM Mktg_Unit_Booking
WHERE IsDeleted <> '1' AND IsApproved = '1'
AND UnitId = 1110 AND ProductType = 'U'
ORDER BY UnitNo
I have run EXPLAIN in the query and I got this:
Any other suggestion on how to improve the speed of the query?
Thank you!
you are doing the cross product, instead of that you should use join.
Don't use sub-queries in select statement instead use proper join on Mktg_Unit_Booking in after from statement.
you query should something look like :
select
sys_tree.TreeName AS PhaseName,
case
WHEN Mktg_Unit_Booking.ProductType = 'U' then prop_unit.UnitNo
else prop_car_park.BayNo
end as UnitNo,
mktg_customer.CustomerName AS CustomerName
FROM Mktg_Unit_Booking
left join sys_tree on sys_tree.TreeId = Mktg_Unit_Booking.ProjectLevelId
left join prop_unit on prop_unit.UnitId = Mktg_Unit_Booking.UnitId
left join prop_car_park on prop_car_park.CarParkId = Mktg_Unit_Booking.UnitId
left join mktg_customer on mktg_customer.CustomerId = Mktg_Unit_Booking.CustomerId
WHERE IsDeleted <> '1' AND IsApproved = '1'
AND UnitId = 1110 AND ProductType = 'U'
ORDER BY UnitNo;
I have assumed that each table consists of only 1 matching tuple. If there are more then your logic needs to be modified.

Select Count Row then update value

Just need some idea
Is there a way I can Select the count then update its value?
Here is my code to be edit.
I'm getting the number of new message in my table message
select count(id) as new from message where owner_id = '1' and status = '1' and isRecieve = '0'
When I get the number of message I want it to set all the message got from select query to isRecieve = 1
is there a way once I query I updte all isRecieve to 1?
like
select count(id) as new from message where owner_id = '1' and status = '1' and isRecieve = '0' then update isRecieve = 1
Thanks.
You should not select COUNT for your case. In fact, what your are trying to achieve is:
UPDATE corresponding records
Discover, how many rows was touched
This can be resolved with:
UPDATE
message
SET
isReceive = '1'
WHERE
owner_id = '1'
AND
status = '1'
AND
isRecieve = '0'
and then either do
SELECT ROW_COUNT()
to retrieve affected rows in SQL, or do something like mysqli_affected_rows() in application (function is in PHP, but the same thing is available in any mysql connection driver in any language).
UPDATE message set
isRecieve = 1 where
owner_id = '1' and
status = '1' and
isRecieve = '0' and
exists (
select 1 from message where
owner_id = '1' and
status = '1' and
isRecieve = '0'
group by id having count(*) = 1
)

MySQL UPDATE field where count on another field in the same table = 1

Please could someone give me the correct syntax for below.
MySQL UPDATE tblcontact SET MainContact = 1
WHERE COUNT(tblcontact.CompanyID) = 1
GROUP BY tblcontact.CompanyID
I get the idea. You want to set the field to 1 where there is only one record. Try this:
UPDATE tblcontact c join
(select CompanyID, count(CompanyID) as cnt
from tblcontact
group by CompanyId
) cc
on c.CompanyId = cc.CompanyId and cnt = 1
SET c.MainContact = 1 ;

CASE or COALESCE performance in WHERE clause for MySQL

I'm wondering which is the better performance or best practice when dealing with multiple criteria in the WHERE clause and NULL values.
WHERE
u.id = COALESCE(user_id, u.id) AND
su.custom_id = COALESCE(student_number, su.custom_id)
OR
WHERE
CASE
WHEN user_id IS NOT NULL AND LENGTH(user_id) > 0
THEN
u.id = user_id
ELSE
su.custom_id = student_number
END
I would avoid both of those approaches. You should be able to accomplish what you are trying to do with a judicious use of AND, OR, IS NULL, and parentheses.
For example, you can rewrite this:
WHERE
u.id = COALESCE(user_id, u.id) AND
su.custom_id = COALESCE(student_number, su.custom_id)
Like this:
WHERE
(user_id IS NULL OR u.id = user_id) AND
(su.custom_id = student_number)
And you can rewrite this:
WHERE
CASE
WHEN user_id IS NOT NULL AND LENGTH(user_id) > 0
THEN
u.id = user_id
ELSE
su.custom_id = student_number
END
As this:
WHERE
(user_id IS NOT NULL AND LENGTH(user_id) > 0 AND u.id = user_id)
OR
(su.custom_id = student_number)
I would suggest using explain and seehow your query plan is. Like:
explain <your select query here>

Help with MySQL sub query

Basically what I have is a comments MySQL table. I have a column called 'parent_id' which tracks if a comment is a reply to another comment.
What I want to do is count all the comments. This was working fine but if you delete a comment and not the replies, it counts them as still active but intact they are deleted.
Here is my MySQL query which at the moment isn't working... Any ideas?
SELECT ic.*
FROM roster_services_items_comments AS ic
WHERE (SELECT icp.id FROM roster_services_items_comments AS icp
WHERE ic.parent_id = ''
OR (icp.id = ic.parent_id AND icp.deleted != 0)
LIMIT 1) IS NOT NULL
What about:
SELECT ic.*, COUNT(icp.parent_id) AS replies_count
FROM roster_services_items_comments AS ic
LEFT JOIN roster_services_items_comments AS icp ON ic.id = icp.parent_id
WHERE ic.deleted != 0
GROUP BY ic.id
HAVING ic.parent_id IS NULL
EDIT: Fixed the count to not count if a comment doesn't have any replies
You should probably add a trigger which marks replies of deleted to be deleted
the problem is that you need recursivly check the current comment for possible parents and parent's parents
you can create a recursive function, which determine has it deleted parents or not
Select Count(*)
From roster_services_items_comments As ic
Where ( ic.parent_id = '' And deleted = 0 )
Or ic.id Not In (
Select ic1.parent_id
From roster_services_items_comments As ic1
Where ic1.deleted = 1
)
Can parent_id really be an empty string? Wouldn't it make more sense for parent_id to be NULL when it was the top most comment? If that were true we'd have:
Select Count(*)
From roster_services_items_comments As ic
Where ( ic.parent_id Is Null And deleted = 0 )
Or ic.id Not In (
Select ic1.parent_id
From roster_services_items_comments As ic1
Where ic1.deleted = 1
)