更新 MySQL 表以双重聚合构造,这取决于表本身

Posted

技术标签:

【中文标题】更新 MySQL 表以双重聚合构造,这取决于表本身【英文标题】:Update a MySQL table to double aggregate of a construct, which depends on the table itself 【发布时间】:2014-05-02 18:21:23 【问题描述】:

我需要更新一个表,但要获得新值,我似乎需要创建一个临时表。原因是我需要计算maxsum。可以吗?

伪代码如下所示:

 UPDATE users u SET usersContribution = [CREATE TEMPORARY TABLE IF NOT EXISTS tmpTbl3 AS
          (SELECT ROUND(max(zz.zachetTimestamp - d.answerDate)) as answerDateDiff
           FROM zachet zz
           JOIN discussionansw d ON d.zachetid=zz.zachetId and d.usersid=zz.usersId and
                                    zz.zachetTimestamp > d.answerDate
           WHERE zz.whoTalk=u.userid and
                 NOT EXISTS (SELECT * FROM discussionansw
                            WHERE zachetid=zz.zachetId and usersid=u.userid')
           GROUP BY zz.zachetId)]
           SELECT SUM(answerDateDiff) FROM tmpTbl3;"

我用方括号表示必须完成的部分,但被 UPDATE 查询忽略...

我同时拥有maxsum,但我看不到避免 tmp 表的方法。但如果可以的话,我们会很高兴有这样的解决方案。


我把答案放在这里,这是我在@flaschenpost 和这篇文章的帮助下得到的:SQL Update to the SUM of its joined values

 CREATE TEMPORARY TABLE IF NOT EXISTS t0tmpTbl3 AS
          (SELECT zz.whoTalk, ROUND(max(zz.zachetTimestamp - d.answerDate)) as answerDateDiff
           FROM zachet zz
           JOIN discussionansw d ON d.zachetid=zz.zachetId and d.usersid=zz.usersId and
                                    zz.zachetTimestamp > d.answerDate
           WHERE 
                 NOT EXISTS (SELECT * FROM discussionansw WHERE zachetid=zz.zachetId and usersid=zz.whoTalk)
           GROUP BY zz.zachetId);

 UPDATE users u
           JOIN (SELECT whoTalk, SUM(answerDateDiff) sumAnswerDateDiff
                 FROM t0tmpTbl3 GROUP BY whoTalk) t
           ON u.usersId=t.whoTalk
           SET u.usersContribution=sumAnswerDateDiff;

【问题讨论】:

那太复杂了。您可以轻松地使用带有连接子句的 update ... select 来获取“外来”值。 @MarcB,那你能不能简单地告诉我怎么做?:) mysqltutorial.org/mysql-update-join @MarcB,你确定你在谈论我的案子吗?我没有看到任何带有 max 或类似内容的示例。 joined 表可以是一个选择。例如update t1 join (select ...) AS foo on t1.bar = foo.baz 【参考方案1】:

你能把它分成两个查询吗?

drop temporary table if exists tmp_maxsumofsomething;

create temporary table tmp_maxsumofsomething 
select max(), sum(), ...
from zachet z inner join discussionansw a on ...
group by...
;

update u inner join tmp_maxsumofsomething t on ... set u.... = t...

临时表仅在创建它们的连接中可见,因此提供了线程安全性。

编辑:只要您的查询有意义,您就可以尝试:

 DROP TEMPORARY TABLE IF EXISTS tmpTbl3;
 CREATE TEMPORARY TABLE tmpTbl3
      SELECT zz.whoTalk as userId, ROUND(max(zz.zachetTimestamp - d.answerDate)) as answerDateDiff
       FROM zachet zz, discussionansw d
      WHERE  d.zachetid=zz.zachetId 
        and d.usersid=zz.usersId and zz.zachetTimestamp > d.answerDate
            # What do you mean ? by: 
            # and (SELECT count(*) FROM discussionansw
            #      WHERE zachetid=zz.zachetId and usersid=u.userid) = 0
            # Think about a reasonable WHERE NOT EXISTS clause!
     GROUP BY zz.whoTalk

然后你有你的临时表加入:

 update users u 
 inner join tmpTbl3 tm on u.userId = tm.userId 
 set u.usersContribution = tm.answerDateDiff

如果您有足够的勇气编写需要这些查询的应用程序,那么您不应该害怕学习更多 SQL 和 MySQL 的一些概念。你来这里是为了探索概念,而不是免费雇佣程序员

【讨论】:

临时取决于你。并且有 sum(max()),而不是 sum,max。如果可以,您可以这样做,但我不明白您的想法。 我使用 EXISTS 语句更新了我的问题。您的回答仍然没有暗示应该用 u.userid 做什么。我会很高兴学习更多的 SQL 概念,但我没有时间全部学习它们,而且我不知道我在这里需要什么。我尝试了联合和临时表,但没有成功。 第一个表为每个拥有 zachet 和 Discussionansw 的用户创建答案,并将这些条目存储在 tmpTbl3 中。第二个表只是将结果复制到表用户。您能否提供有关您的条件计数(*)= 0 的任何提示?该用户应该没有其他答案吗? 哦。现在我看到了你的想法。我会试试看。您的答案中唯一遗漏的是 SUM,但它可以通过额外的 tmpTable 来实现。不知道它是否是最优的,但它应该可以工作。 是的,这个用户应该没有答案。我在问题帖子中更改了这部分。

以上是关于更新 MySQL 表以双重聚合构造,这取决于表本身的主要内容,如果未能解决你的问题,请参考以下文章

t-SQL 更新表以删除重叠的时间范围

更改和更新层次关系表以查看是不是有子级的过程

如何更新作为 MySQL 中另一个表的聚合结果的字段?

带有表变量的动态查询以循环遍历所有表以在数据库中更新

更新 Access 链接表以使用 UNC 路径

更新表以按分组列显示总计 SQL Server 2008 R2