error query update mysql - mysql

I have an query:
update customers_training_malaysia
set
period_id = (select b.id
from customers_training_malaysia a,training_schedules_malaysia b
where a.sch_code=b.sch_code order by a,id)
where
sch_code = (select b.sch_code
from customers_training_malaysia a,training_schedules_malaysia b
where a.sch_code = b.sch_code order by a.id)
I tried to run following query update, but I get only the error
more than one row returned by a subquery used as an expression
What shall I do to correct the sql query?

You must get all your subqueries in
set [field_name] = ([subquery])
and check that this queries returning only one record in results.
That is reason for the error - multiple results in your subqueries
Try this:
update customers_training_malaysia
set
period_id = b.id
where
sch_code = (select b.sch_code
from customers_training_malaysia a,training_schedules_malaysia b
where a.sch_code = b.sch_code order by a.id)

order by a,id)
Is this a typo?
**","** used it should be a.id
And Add from the other answer Below it might be returning more than one result, because of order by condition i assumed that!

Related

MySQL Count returns More Rows than it Should

I am attempting to count the number of rows from a given query. But count returns more rows than it should. What is happening?
This query returns only 1 row.
select *
from `opportunities`
inner join `companies` on `opportunities`.`company_id` = `companies`.`id`
left join `opportunityTags` on `opportunities`.`id` = `opportunityTags`.`opportunity_id`
where `opportunities`.`isPublished` = '1' and `opportunities`.`Company_id` = '1'
group by `opportunities`.`id` ;
This query returns that there are 3 rows.
select count(*) as aggregate
from `opportunities`
inner join `companies` on `opportunities`.`company_id` = `companies`.`id`
left join `opportunityTags` on `opportunities`.`id` = `opportunityTags`.`opportunity_id`
where `opportunities`.`isPublished` = '1' and `opportunities`.`Company_id` = '1'
group by `opportunities`.`id`;
When you select count(*) it is counting before the group by. You can probably (unfortunately my realm is SQL Server and I don't have a mySQL instance to test) fix this by using the over() function.
For example:
select count(*) over (partition by `opportunities`.`id`)
EDIT: Actually doesn't look like this is available in mySQL, my bad. How about just wrapping the whole thing in a new select statement? It's not the most elegant solution, but will give you the figure you're after.

MySQL update value from the same table with count

What I want to do is to set every patient its unique patient code which starts with 1 and it's not based on row id. Id only specifies order. Something like this:
patient_id patient_code
2 1
3 2
4 3
This is my query:
UPDATE patients p1
SET p1.patient_code = (
SELECT COUNT( * )
FROM patients p2
WHERE p2.patient_id <= p1.patient_id
)
But it is throwing error:
#1093 - You can't specify target table 'p1' for update in FROM clause
I found this thread: Mysql error 1093 - Can't specify target table for update in FROM clause.But I don't know how to apply approved answer this to work with subquery WHERE which is necessary for COUNT.
UPDATE
patients AS p
JOIN
( SELECT
p1.patient_id
, COUNT(*) AS cnt
FROM
patients AS p1
JOIN
patients AS p2
ON p2.patient_id <= p1.patient_id
GROUP BY
p1.patient_id
) AS g
ON g.patient_id = p.patient_id
SET
p.patient_code = g.cnt ;
I found working solution, but this is just workaround:
SET #code=0;
UPDATE patients SET patient_code = (SELECT #code:=#code+1 AS code)
Try this,
UPDATE patients p1 INNER JOIN
(
SELECT COUNT(*) as count,patient_id
FROM patients
group by patient_id
)p2
SET p1.patient_code=p2.count
WHERE p2.patient_id <= p1.patient_id
SQL_LIVE_DEMO
Thanks to Mari's answer I found a solution to my similar problem. But I wanted to add a bit of an explanation which for me at first wasn't too clear from his answer.
What I wanted to do would have been as simple as the following:
UPDATE my_comments AS c
SET c.comment_responses = (
SELECT COUNT(c1.*) FROM my_comments AS c1
WHERE c.uid = c.parent_uid
);
Thanks to Mari I then found the solution on how to achieve this without running into the error You can't specify target table 'p1' for update in FROM clause:
UPDATE my_comments AS c
INNER JOIN (
SELECT c1.parent_uid, COUNT(*) AS cnt
FROM my_comments AS c1
WHERE c1.parent_uid <> 0
GROUP BY c1.parent_uid
) AS c2
SET c.comment_responses = c2.cnt
WHERE c2.parent_uid = c.uid;
My problems before getting to this solution were 2:
the parent_uid field doesn't always contain an id of a parent which is why I added the WHERE statement in the inner join
I didn't quite understand why I would need the GROUP BY until I executed the SELECT statement on it's own and the answer is: because COUNT groups the result and really counts everything. In order to prevent this behavior the GROUP BY is needed. In my case I didn't have to group it by uid though but the parent_uid to get the correct count. If I grouped it by uid the COUNT would always be 1 but the parent_uid existed multiple times in the result. I suggest you check the SELECT statement on it's own to check if it's the result you expect before you execute the full UPDATE statement.

mysql update query with sub query

Can anyone see what is wrong with the below query?
When I run it I get:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'a where a.CompetitionID = Competition.CompetitionID' at line 8
Update Competition
Set Competition.NumberOfTeams =
(
SELECT count(*) as NumberOfTeams
FROM PicksPoints
where UserCompetitionID is not NULL
group by CompetitionID
) a
where a.CompetitionID = Competition.CompetitionID
The main issue is that the inner query cannot be related to your where clause on the outer update statement, because the where filter applies first to the table being updated before the inner subquery even executes. The typical way to handle a situation like this is a multi-table update.
Update
Competition as C
inner join (
select CompetitionId, count(*) as NumberOfTeams
from PicksPoints as p
where UserCompetitionID is not NULL
group by CompetitionID
) as A on C.CompetitionID = A.CompetitionID
set C.NumberOfTeams = A.NumberOfTeams
Demo: http://www.sqlfiddle.com/#!2/a74f3/1
Thanks, I didn't have the idea of an UPDATE with INNER JOIN.
In the original query, the mistake was to name the subquery, which must return a value and can't therefore be aliased.
UPDATE Competition
SET Competition.NumberOfTeams =
(SELECT count(*) -- no column alias
FROM PicksPoints
WHERE UserCompetitionID is not NULL
-- put the join condition INSIDE the subquery :
AND CompetitionID = Competition.CompetitionID
group by CompetitionID
) -- no table alias
should do the trick for every record of Competition.
To be noticed :
The effect is NOT EXACTLY the same as the query proposed by mellamokb, which won't update Competition records with no corresponding PickPoints.
Since SELECT id, COUNT(*) GROUP BY id will only count for existing values of ids,
whereas a SELECT COUNT(*) will always return a value, being 0 if no records are selected.
This may, or may not, be a problem for you.
0-aware version of mellamokb query would be :
Update Competition as C
LEFT join (
select CompetitionId, count(*) as NumberOfTeams
from PicksPoints as p
where UserCompetitionID is not NULL
group by CompetitionID
) as A on C.CompetitionID = A.CompetitionID
set C.NumberOfTeams = IFNULL(A.NumberOfTeams, 0)
In other words, if no corresponding PickPoints are found, set Competition.NumberOfTeams to zero.
For the impatient:
UPDATE target AS t
INNER JOIN (
SELECT s.id, COUNT(*) AS count
FROM source_grouped AS s
-- WHERE s.custom_condition IS (true)
GROUP BY s.id
) AS aggregate ON aggregate.id = t.id
SET t.count = aggregate.count
That's #mellamokb's answer, as above, reduced to the max.
You can check your eav_attributes table to find the relevant attribute IDs for each image role, such as;
Then you can use those to set whichever role to any other role for all products like so;
UPDATE catalog_product_entity_varchar AS `v` INNER JOIN (SELECT `value`,`entity_id` FROM `catalog_product_entity_varchar` WHERE `attribute_id`=86) AS `j` ON `j`.`entity_id`=`v`.entity_id SET `v`.`value`=j.`value` WHERE `v`.attribute_id = 85 AND `v`.`entity_id`=`j`.`entity_id`
The above will set all your 'base' roles to the 'small' image of the same product.

UPDATE Syntax with ORDER BY, LIMIT and Multiple Tables

Learning SQL, sorry if this is rudimentary. Trying to figure out a working UPDATE solution for the following pseudoish-code:
UPDATE tableA
SET tableA.col1 = '$var'
WHERE tableA.user_id = tableB.id
AND tableB.username = '$varName'
ORDER BY tableA.datetime DESC LIMIT 1
The above is more like SELECT syntax, but am basically trying to update a single column value in the latest row of tableA, where a username found in tableB.username (represented by $varName) is linked to its ID number in tableB.id, which exists as the id in tableA.user_id.
Hopefully, that makes sense. I'm guessing some kind of JOIN is necessary, but subqueries seem troublesome for UPDATE. I understand ORDER BY and LIMIT are off limits when multiple tables are involved in UPDATE... But I need the functionality. Is there a way around this?
A little confused, thanks in advance.
The solution is to nest ORDER BY and LIMIT in a FROM clause as part of a join. This let's you find the exact row to be updated (ta.id) first, then commit the update.
UPDATE tableA AS target
INNER JOIN (
SELECT ta.id
FROM tableA AS ta
INNER JOIN tableB AS tb ON tb.id = ta.user_id
WHERE tb.username = '$varName'
ORDER BY ta.datetime DESC
LIMIT 1) AS source ON source.id = target.id
SET col1 = '$var';
Hat tip to Baron Schwartz, a.k.a. Xaprb, for the excellent post on this exact topic:
http://www.xaprb.com/blog/2006/08/10/how-to-use-order-by-and-limit-on-multi-table-updates-in-mysql/
You can use following query syntax:
update work_to_do as target
inner join (
select w. client, work_unit
from work_to_do as w
inner join eligible_client as e on e.client = w.client
where processor = 0
order by priority desc
limit 10
) as source on source.client = target.client
and source.work_unit = target.work_unit
set processor = #process_id;
This works perfectly.

Getting this query to work?

Heya!, I have the below query:
SELECT t1.pm_id
FROM fb_user_pms AS t1,
fb_user_pm_replies AS t2
WHERE (t1.pm_id = '{$pm_id}'
AND t1.profile_author = '{$username}'
OR t1.pm_author = '{$username}'
AND t1.pm_id = t2.pm_id
AND t2.pm_author = '{$username}'
AND COUNT(t2.reply_id) > 0)
AND t1.deleted = 0
However, I'm getting a grouping error - my guess is its caused by the AND COUNT(t2.reply_id) > 0?
How can I rectify the above query to make it work.
Hope someone can help.
Cheers!
The aggregate function COUNT can't go in the WHERE clause. You should use a GROUP BY and put it in the HAVING clause.
SELECT t1.pm_id
FROM fb_user_pms AS t1
JOIN fb_user_pm_replies AS t2 ON t1.pm_id = t2.pm_id
WHERE (
(t1.pm_id = '{$pm_id}' AND t1.profile_author = '{$username}') OR
(t1.pm_author = '{$username}' AND t2.pm_author = '{$username}')
) AND t1.deleted = 0
GROUP BY t1.pm_id
HAVING COUNT(t2.reply_id) > 0
If t2.reply_id is a NOT NULL column then you don't need the HAVING clause at all.
The error is because you can't use an aggregate function (COUNT, MIN, MAX, AVG, etc) in the WHERE clause, without it being inside a subquery. Only the HAVING clause allows you to use aggregates without being wrapped in subqueries.
But checking for replies to be more than zero is not necessary on an INNER JOIN - that guarantees that there will be at least one reply associated to the fb_user_pms record. The JOIN also means that the information in t1 will be duplicated for every supported record in fb_user_pm_replies. IE: If a fb_user_pms record has three fb_user_pm_replies records related to it, you'll see the fb_user_pms record in the result set three times.
The query you want to use is:
SELECT t1.pm_id
FROM fb_user_pms AS t1
WHERE t1.pm_id = '{$pm_id}'
AND '{$username}' IN (t1.profile_author, t1.pm_author)
AND t1.deleted = 0
AND EXISTS(SELECT NULL
FROM fb_user_pm_replies AS t2
WHERE t2.pm_id = t1.pm_id
AND t2.pm_author = '{$username}')
The EXISTS clause returns true or false, based on the WHERE criteria. It also won't duplicate t1 results.
The condition with COUNT must be in the HAVING part. It can not be part of the WHERE part.
The SELECT part must be also use aggregate functions for example MAX(t1.pm_id)