mysql用子查询更新查询

use*_*043 52 mysql sql

任何人都可以看到以下查询有什么问题?

当我运行它时,我得到:

#1064 - 您的SQL语法有错误; 查看与您的MySQL服务器版本对应的手册,以便在第8行的'a where a.CompetitionID = Competition.CompetitionID'附近使用正确的语法

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
Run Code Online (Sandbox Code Playgroud)

mel*_*okb 135

主要问题是内部查询不能与where外部update语句中的子句相关,因为where子过滤器首先应用于内部子查询甚至执行之前更新的表.处理这种情况的典型方法是多表更新.

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
Run Code Online (Sandbox Code Playgroud)

演示:http://www.sqlfiddle.com/#!2/ a74f3/1


小智 20

谢谢,我没有INNER JOIN UPDATE的想法.

在原始查询中,错误是命名子查询,子查询必须返回一个值,因此不能为别名.

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
Run Code Online (Sandbox Code Playgroud)

应该为每个比赛记录做好准备.

要注意:

效果与mellamokb提出的查询不完全相同,后者不会更新没有相应PickPoints的比赛记录.

因为 SELECT id, COUNT(*) GROUP BY id只计算id的现有值,

而a SELECT COUNT(*)将始终返回一个值,如果没有选择记录则为0.

这对您来说可能是,也可能不是.

0感知版的mellamokb查询将是:

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)
Run Code Online (Sandbox Code Playgroud)

换句话说,如果找不到相应的PickPoints,则将Competition.NumberOfTeams设置为零.


sun*_*sun 10

对于不耐烦:

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
Run Code Online (Sandbox Code Playgroud)

这是@mellamokb的回答,如上述,减少到了极致.