【问题标题】:AVG of last three entries by date按日期计算的最后三个条目的 AVG
【发布时间】:2017-09-13 18:19:44
【问题描述】:

Table

我在下面有这张表 我的目标是取 perDem、perGop、perInd 列的平均值,但只取最后三个基于日期的列。我如何编写这样的查询,我尝试使用 order by、group by 但无法获得结果。我需要每列的平均值,但只需要基于当天的最后三个条目。因此,对于阿拉巴马州来说,例如平均 perDem、perGop、PerInd,但如果按天排序,则只有最后三行。 这是我到目前为止所拥有的,但我需要这个仅根据为该特定状态提交的日期取最后三个的平均值。

select polls.state,evotes,avg(perDem),avg(perGOP),avg(perInd)
             from polls,electoral
             where electoral.state=polls.state
             group by electoral.state,polls.state";

【问题讨论】:

  • 您只列出了三列,但您的评论 but only the last three based on the day 表明应该有更多。请澄清。
  • 您的意思是您对每天最近的三个条目感兴趣吗?
  • 是的,这就是我的意思。
  • 你如何确定它们发生的顺序(以便我们可以确定哪些是最近的)?
  • 这是一个查询,我目前有 select polls.state,evotes,avg(perDem),avg(perGOP),avg(perInd) from polls,electoral whereelectoral.state=polls。州组按选举.state,polls.state"; 它只取所有民意调查的平均值,但我需要最后三个

标签: php mysql sql


【解决方案1】:

一种可能的方法是利用 MySQL 用户定义的变量来模拟其他数据库中可用的分析/窗口函数。

SELECT v.state
     , e.evotes
     , AVG(IF(v.n<=3,v.perDem,NULL)) AS perDem_avg_last_3_day
     , AVG(IF(v.n<=3,v.perGOP,NULL)) AS perGOP_avg_last_3_day
     , AVG(IF(v.n<=3,v.perInd,NULL)) AS perInd_avg_last_3_day
  FROM ( SELECT @i := IF(p.state = @p_state,@i+1,1) AS n
              , @p_state := p.state AS `state`
              , p.perDem
              , p.perGOP
              , p.perInd
           FROM polls p
          CROSS
           JOIN ( SELECT @p_state = '', @i := 0 ) i
          ORDER
             BY p.state DESC
              , p.day DESC
       ) v
  JOIN electoral e
    ON e.state = v.state
 GROUP BY v.state, e.evotes
 ORDER BY v.state

注意:MySQL 参考手册特别警告不要使用这种类型的用户定义变量;但在 MySQL 5.6 之前,我们观察到精心构造的 SELECT 语句的一致行为。)

从性能的角度来看,这种方法对于大型集合并不理想(具体化内联视图,并且可能需要“使用文件排序”操作。)

【讨论】:

  • 我收到此错误代码:1054。“on 子句”中的未知列“p.state”
  • 把它改成ON e.state = v.state
  • 更改然后导致此错误 LIMIT 0, 1000 错误代码:1055。SELECT 列表的表达式 #2 不在 GROUP BY 子句中,并且包含非聚合列 'voting.e.evotes' 不是功能上依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 0.000 秒不兼容
  • 所以只需将e.evotes 添加到 GROUP BY 子句中。或者从 SELECT 列表中删除 e.evotes。或者将 sql_mode 更改为不包含 ONLY_FULL_GROUP_BY 的设置。
【解决方案2】:

请尝试以下...

set @rowNum := 0;
set @state := '';

SELECT state,
       AVG( perDem ) AS avgPerDem,
       AVG( perGOP ) AS avgPerGOP,
       AVG( perInd ) AS avgPerInd
FROM
(
    SELECT day AS day,
           state AS state,
           perDem AS perDem,
           perGOP AS perGOP,
           perInd AS perInd,
           @rowNum := if ( @state = state,
                           @rowNum + 1,
                           1 ) AS rowNum,
           @state := state AS valueHolder
    FROM polls
    ORDER BY state,
             day DESC
) rowNumGenerator
WHERE rowNum <= 3
GROUP BY state
ORDER BY state;

这里的内部查询返回对内容进行排序,将polls 的内容按字母顺序按state 排序,对于每个状态,它进一步按day 对行进行排序,从大到小。

完成此操作后,它会返回感兴趣的字段(daystateperDemperGOPperInd)以及它根据以下模式生成的行号。 .

遇到新状态时,它会为第一行提供1 的行号。

该状态的每个后续行都被赋予下一个可用行号。

这有效地为每个记录在有序列表中的位置分配了一个数字,相对于 state 的第一条记录。

外部查询仅选择其位置/行号将其置于前三名的行作为其state

结果数据集的记录然后按state 分组。请注意,外部SELECT 语句不知道内部使用的分组,因此不能安全地假设它。因此,除非另有说明,否则它将假定没有分组。

然后计算每个州的 per 字段的平均值,并将所有指定字段返回给用户。

如果您有任何问题或cmets,请随时发表相应的评论。

【讨论】:

  • 删除了多余的行。
  • 添加了一个缺失的行。
  • LIMIT 0, 1000 错误代码:1055。SELECT 列表的表达式 #2 不在 GROUP BY 子句中,并且包含在功能上不依赖于列的非聚合列 'voting.polls.perDem'
  • 嗯...我会调查的。
  • 我也遇到了同样的问题 group by :( 非常感谢您的帮助。我真的需要阅读数据库书籍,但目前时间很短。
猜你喜欢
  • 2021-11-10
  • 2019-08-28
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 2022-11-02
相关资源
最近更新 更多