MySql使用不同的位置在同一个表上为同一个用户进行多次计数并进行更新

时间:2014-08-04 12:58:47

标签: mysql sql

我在这里遇到了两件事,需要在一个sql语句中完成。

一,是在同一个桌子上为同一个用户做不同的where条件的四个计数,第二个是用同一个用户的那些计数数据更新另一个表。

整件事让我陷入困境。我对基本的update table select count(*) etc事情没问题,但这怎么可行呢?

的UserData

"userId"    "postId"    "postStatus"    "postTitle"
"1"         "1"         "0"             "Title 1"
"1"         "2"         "0"             "Title 2"
"1"         "3"         "0"             "Title 3"
"1"         "4"         "0"             "Title 4"
"1"         "5"         "1"             "Title 5"
"1"         "6"         "1"             "Title 6"
"1"         "7"         "1"             "Title 7"
"1"         "8"         "6"             "Title 8"
"1"         "9"         "5"             "Title 9"
"1"         "10"        "5"             "Title 10"
"2"         "11"        "0"             "Title 11"
"2"         "12"        "0"             "Title 12"
"2"         "13"        "0"             "Title 13"
"2"         "14"        "1"             "Title 14"

userStats

"userId"    "published" "inactive"  "recalled"  "deleted"
"1"         "0"         "0"         "0"         "0"

我失败的sql

update userStats set 
published = select count (postStatus) published where postStatus = 0, 
inactive = select count (postStatus) inactive where postStatus = 1,
recalled = select count (postStatus) recalled where postStatus = 5, 
deleted = select count (postStatus) deleted where postStatus = 6
from userData where userId = 1;

预期结果

"userId"    "published" "inactive"  "recalled"  "deleted"
"1"         "4"         "3"         "2"         "1"

最后,可以从userData为userId = 1选择count,并使用该用户的数据更新userStats。你能帮忙吗?

解决方案

update userStats us
join (select
  userId,
  sum(postStatus = 0) published,
  sum(postStatus = 1) inactive,
  sum(postStatus = 5) recalled,
  sum(postStatus = 6) deleted
from userData where userId = 1) d on d.userId = us.userId set
us.published = d.published,
us.inactive = d.inactive,
us.recalled = d.recalled,
us.deleted = d.deleted;

2 个答案:

答案 0 :(得分:2)

此问题唯一有意义的方法是,userData的所有示例行都是针对userId 1的,并且您希望使用其总计更新所有用户。

首先,这里是对数据的查询:

select
  userId,
  sum(postStatus = 0) published,
  sum(postStatus = 1) inactive,
  sum(postStatus = 5) recalled,
  sum(postStatus = 6) deleted
from userData
group by 1

顺便说一下,总计工作的原因是,在mysql中,true为1,false为0,所以求和条件计算它的真实次数!与冗长的案例陈述相比,它使查询非常简洁。

现在更新另一个表,使用mysql的特殊update-with-join语法:

update userStats us
join (select
  userId,
  sum(postStatus = 0) published,
  sum(postStatus = 1) inactive,
  sum(postStatus = 5) recalled,
  sum(postStatus = 6) deleted
from userData
group by 1) d on d.userId = us.userId set
us.published = d.published,
us.inactive = d.inactive,
us.recalled = d.recalled,
us.deleted = d.deleted
where us.userId = 1 -- optional where clause. leave out to update all users

这将在一个查询中正确更新所有用户。

这非常有效,因为它会通过userData表进行一次传递(而不是使用单独的子查询进行4次传递),并且所有用户都会刷新其统计信息(而不是为每个用户分别进行查询)。 / p>

我实际上只想更新一个特定用户,只需在查询末尾添加where us.userId = ?即可。

我鼓励您考虑使用原始数据而不是将结果非规范化到userStats表中,除非有非常令人信服的理由。它是一种缓存形式,缓存带来许多隐藏的维护开销和微妙的问题。

答案 1 :(得分:1)

使用带有JOIN声明

UPDATE以这种方式尝试
update userStats  
join
(
select userId,
sum(case when postStatus = 0 then 1 else 0 end) as pub, 
sum(case when postStatus = 1 then 1 else 0 end) as inac,
sum(case when postStatus = 5 then 1 else 0 end) as recal,
sum(case when postStatus = 6 then 1 else 0 end) as del
from userData
) tab on userStats.userId = tab.userId
set published = tab.pub,
inactive = tab.inac,
recalled = tab.recal,
deleted = tab.del
where userStats.userId = 1