【问题标题】:Sum of values for all accounts using the most recent date for each使用每个帐户的最近日期的所有帐户的值总和
【发布时间】:2019-07-03 21:00:36
【问题描述】:

随着时间的推移,帐户的价值会有所不同。我想知道在帐户拥有数据的最近日期,所有帐户的价值是多少。

Account      Date     Value
Account 1    1/1/19   12
Account 1    1/3/19   32
Account 1    1/12/19  52
Account 2    4/1/18   123
Account 2    4/22/18  42
Account 3    2/1/19   11
Account 3    7/1/18   64
Account 3    8/12/18  74

对于这个数据集,我希望我的最终结果是 105,因为 52+42+11 是每个帐户最近日期的值。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    有多种方法,我更喜欢的方法是自连接,像这样:

    select Account, Date, Value
    from accounts as a inner join (
        select Account, max(Date) as maxDate
        from accounts
        group by Account
    ) as t on a.Account = t.Account and a.Date = t.maxDate
    

    【讨论】:

    • 这给了我每个帐户的价值。然后我需要一个单独的操作来对新表上的值求和吗?
    • 如果您需要所有的总和 - 只需将 select Account, Date, Value 替换为 select sum(Value)
    【解决方案2】:

    您想要汇总日期为帐户最大日期的那些行的值:

    select sum(value)
    from mytable
    where (account, date) in (select account, max(date) from mytable group by account);
    

    从 MySQL 8 开始,您应该能够使用窗口函数来避免两次读取表:

    select sum(value)
    from
    (
      select value, date = max(date) over (partition by account) as is_latest_for_account
      from mytable
    )
    where is_latest_for_account;
    

    【讨论】:

    • 我想就是这样!
    • @Justin Kelley:谢谢。我为可能(或可能不会)运行得更快的较新 MySQL 版本添加了替代方案。
    【解决方案3】:

    先按账户分组,得到每个账户的最大日期,然后加入表:

    select sum(t.value) totalvalue
    from tablename t inner join (
      select account, max(date) date
      from tablename
      group by account
    ) g on g.account = t.account and g.date = t.date
    

    你也可以用 NOT EXISTS 来做:

    select sum(t.value) totalvalue
    from tablename t 
    where not exists (
      select 1 from tablename
      where account = t.account and date > t.date
    )
    

    请参阅demo
    结果:

    > | totalvalue |
    > | ---------: |
    > |        105 |
    

    【讨论】:

      【解决方案4】:

      做一些类似的事情

      select max(date), account
      from table
      group by account
      

      这应该会为您提供与每个帐户关联的最新日期。然后,您可以创建一个 CTE 并按帐户和日期重新加入它。像这样的。

      with q as (
        select max(date), account
        from table
        group by account
      ) select t1.account, t1.date, t1.value  
        from table t1 
        join q on t1.account = q.account and t1.date = q.date
      

      【讨论】:

      • 注意cte(with ...)只有部分版本的mysql支持,最好提一下
      • 可以复制 CTE |在很多方面模仿其他 SQL 版本,就像这里已经给出的答案一样。
      • 我已经为你格式化了代码。 (使用{} 按钮可以轻松完成。)
      【解决方案5】:

      我喜欢为此使用相关子查询:

      select a.*
      from accounts a
      where a.date = (select max(a2.date)
                      from accounts a2
                      where a2.account = a.account
                     );
      

      特别是,这可以利用accounts(account, date) 上的索引。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-03
        • 2022-10-04
        • 1970-01-01
        • 2013-02-22
        • 2014-08-13
        • 2013-06-06
        • 2021-11-04
        • 1970-01-01
        相关资源
        最近更新 更多