In my MySQL database, I have two tables. I am trying to sum up the scores in the two tables. First table named term2 has a particular column named Total_Score, and a column named StudentID. The second table named overall also has a column named Total_Score and a column named StudentID. What I want to do is UPDATE the value of overall.Total_Score by summing up the values in term2.Total_Score with the values in overall.Total_Score, and place the result in overall.Total_Score. Below is the code I am using, but when I have more than one row, I get the error above. Have a look at my code and assist, please. Thank you in advance.
UPDATE overall SET Total_Score = ( SELECT (
ot.Total_Score + op.Total_Score
) AS Total_Score
FROM (
SELECT StudentID, Total_Score
FROM term2
GROUP BY StudentID
) AS ot
INNER JOIN (
SELECT StudentID, Total_Score
FROM overall
GROUP BY StudentID
) AS op ON ( op.StudentID = ot.StudentID ) )
Try the below - you need an update join and your syntax was incorrect
update overall o inner join
(
SELECT op.StudentID,
sum(ot.total_score) as Total_Score_ot,
sum(op.total_score) as Total_Score_op
FROM term2 ot inner join overall op on op.StudentID = ot.StudentID
GROUP BY op.StudentID
) as o1 on o.StudentID = o1.StudentID
SET Total_Score=Total_Score_ot+Total_Score_op
I assume you want to replace the overall value with the calculated value. The key idea is to aggregate before joining the tables together:
update overall o join
(select t.StudentId, sum(t.total_score) as total_score
from term2 t
group by t.StudentId
) t
using (StudentId)
set o.Total_Score = t.Total_Score;
If you want to increment the stored value by the total in term2, then use:
set o.Total_Score = o.Total_Score + t.Total_Score;
If instead you want to replace the stored value for all students, even those with no rows in term2, then use left join:
update overall o left join
(select t.StudentId, sum(t.total_score) as total_score
from term2 t
group by t.StudentId
) t
using (StudentId)
set o.Total_Score = coalesce(t.Total_Score, 0);
Related
Count non-null values directly from select statement (not using where) on a left joint table
count(*) as comments Need this to provide count of non-null values only. Also, inner join is not a solution because, that does not include content which have zero comments in count(distinct (t1.postId)) as no_of_content
select t1.tagId as tagId, count(distinct (t1.postId)) as no_of_content, count(*) as comments
from content_created as t1
left join comment_created as t2
on t1.postId=t2.postId
where
( (t1.tagId = "S2036623" )
or (t1.tagId = "S97422" )
)
group BY 1
Though Posting the sample data might help us more to answer this but you can update your count function to -
COUNT(CASE WHEN postId IS NULL THEN 1 END) as comments
Count only counts non-null values. What you need to do is reference the right hand side table's column explicitly. So instead of saying count(*) use count(right_joined_table.join_key).
Here's a full example using BigQuery:
with left_table as (
select num
from unnest(generate_array(1,10)) as num
), right_table as (
select num
from unnest(generate_array(2,10,2)) as num
)
select
count(*) as total_rows,
count(l.num) as left_table_counts,
count(r.num) as non_null_counts
from left_table as l
left outer join right_table as r
on l.num = r.num
This gives you the following results:
The following query always outputs SUM for all rows instead of per userid. Not sure where else to look. Please help.
SELECT * FROM assignments
LEFT JOIN (
SELECT SUM(timeworked) AS totaltimeworked
FROM time_entries
) assignments ON (userid = assignments.userid AND ticketid = ?)
WHERE ticketid = ?
ORDER BY assigned,scheduled
If you want to keep the SELECT *, you would have to add a group by clause in the subquery. Something like this
SELECT * FROM assignments
LEFT JOIN (
SELECT SUM(timeworked) AS totaltimeworked
FROM time_entries
GROUP BY userid
) time_entriesSummed ON time_entriesSummed.userid = assignments.userid
WHERE ticketid = ?
ORDER BY assigned,scheduled
But a better way would be to change the SELECT * to instead select the fields you want a add a group by clause directly. Something like this
SELECT
assignments.id,
assignments.assigned,
assignments.scheduled,
SUM(time_entries.timeworked) AS totalTimeworked
FROM assignments
LEFT JOIN time_entries
ON time_entries.userid = assignments.userid
GROUP BY assignments.id, assignments.assigned, assignments.scheduled
Edit 1
Included table names in query 2 as mentioned in chameera's comment below
I tryed to find an answer for this based on other questions, but I couldn't implement the logic into my necessity.
I can easily get the informations I need, however I can't update a table with those informations.
I have selected all the necessary values using the following query:
select `roleid`,
(select count(`killerid`) from `kills` where `killerid`=`roleid`) as `kills`,
(select count(`corpseid`) from `kills` where `corpseid`=`roleid`) as `deaths`
from `characters`
So this query returns the character's ID with its respective kills and deaths number.
Now, I need to know: How can I update table "characters", setting rows "kills" and "deaths" to the returned values in the query?
Thank you for your time.
UPDATE characters c
LEFT JOIN
( SELECT killerid, count(*) as kill_num FROM kills GROUP BY killerid ) k1
ON c.roleid = k1.killerID
LEFT JOIN
( SELECT corpseid, count(*) as death_num FROM kills GROUP BY corpseid ) k2
ON c.roleid = k2.corpseID
SET c.kills = k1.kill_num, c.deaths = k2.death_num
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.
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.