【问题标题】:SQL: calculating the change in total for each day using dateSQL:使用日期计算每天的总变化
【发布时间】:2019-03-29 09:38:37
【问题描述】:

我有下表:

Date        |  Store  |  Total
2018-05-02     ABC       56.98
2018-05-02     DEF       60.34 
2018-05-02     XYZ       46.50
2018-05-03     ABC       80.43
2018-05-03     DEF       70.09
2018-05-03     XYZ       95.98
2018-05-04     ABC       43.52
2018-05-04     DEF       90.23
2018-05-04     XYZ       88.12

我正在尝试创建一个查询,该查询将输出上表以及名为 PrevTotal 的附加列,对于每个商店,该列将在前一天获得其总计。我还想忽略输出表中具有第一个日期(2018-05-02)的所有条目(因为您无法获得第一天的前一个总数)。 例如。输出应该是:

Date        |   Code   |   Total   |   PrevTotal 
2018-05-03      ABC        80.43       56.98
2018-05-03      DEF        70.09       60.34
2018-05-03      XYZ        95.98       46.50
2018-05-04      ABC        43.52       80.43
2018-05-04      DEF        90.23       60.34
2018-05-04      XYZ        88.12       95.98      

我不确定如何创建一个可以帮助我执行此操作的查询。任何见解都值得赞赏。

【问题讨论】:

标签: mysql sql date


【解决方案1】:

这对我来说很好用。

SELECT s2.*, s1.Total 
FROM Stores s1
LEFT JOIN Stores s2 on s1.Store = s2.Store
     AND DATEDIFF(day, s2.Date, s1.Date) = -1

WHERE s2.Total IS NOT NULL
ORDER BY s1.Date, s1.Store

【讨论】:

    【解决方案2】:

    您可以使用 2nd max id like 但 null 数据,您无法避免更好,您只需在获取/显示时忽略数据:

    SELECT tbl2.Date, tbl2.Store, tbl2.total, 
    (select total from test_table tbl1 where tbl1.Store = tbl2.Store and tbl1.id < tbl2.id) as prev_Total 
    FROM `test_table` tbl2
    

    结果:

    Date       |   Store  |  total | prev_Total |
    --------------------------------------------
    2019-03-21 |   ABC    |  56.98 | NULL       |
    --------------------------------------------
    2019-03-21 |   DEF    |  60.34 | NULL       |
    --------------------------------------------
    2019-03-21 |   XYZ    |  46.50 | NULL       |
    --------------------------------------------
    2019-03-21 |   ABC    |  80.43 | 56.98      |
    --------------------------------------------
    2019-03-21 |   DEF    |  70.09 | 60.34      |
    --------------------------------------------
    

    【讨论】:

      【解决方案3】:

      如果您使用的是最新版本的 MySQL,可以使用 windowing 函数使代码更具可读性

      现场测试:https://www.db-fiddle.com/f/pKAbtGWF4paTxkbzA8ieST/0

      with a as 
      (
        select 
            date, store, total, 
            lag(total) over(partition by store
                            order by date) as prev_total
        from t
      )
      select *
      from a
      where prev_total is not null
      order by date, store
      

      输出:

      | date                | store | total | prev_total |
      | ------------------- | ----- | ----- | ---------- |
      | 2018-05-03 00:00:00 | ABC   | 80.43 | 56.98      |
      | 2018-05-03 00:00:00 | DEF   | 70.09 | 60.34      |
      | 2018-05-03 00:00:00 | XYZ   | 95.98 | 46.5       |
      | 2018-05-04 00:00:00 | ABC   | 43.52 | 80.43      |
      | 2018-05-04 00:00:00 | DEF   | 90.23 | 70.09      |
      | 2018-05-04 00:00:00 | XYZ   | 88.12 | 95.98      |
      

      【讨论】:

        【解决方案4】:

        我猜以前的总数不会总是从日期开始 - 1 天,但可能天之间会有间隔,所以你必须找到每个商店的上一个日期:

        select t.*, tt.total prevtotal
        from tablename t inner join tablename tt
        on 
          tt.store = t.store 
          and 
          tt.date = (
            select max(date) from tablename where store = t.store and date < t.date
          )
        

        请参阅demo
        结果:

        | date       | store | total | prevtotal |
        | ---------- | ----- | ----- | --------- |
        | 2018-05-03 | ABC   | 80.43 | 56.98     |
        | 2018-05-03 | DEF   | 70.09 | 60.34     |
        | 2018-05-03 | XYZ   | 95.98 | 46.5      |
        | 2018-05-04 | ABC   | 43.52 | 80.43     |
        | 2018-05-04 | DEF   | 90.23 | 70.09     |
        | 2018-05-04 | XYZ   | 88.12 | 95.98     |
        

        【讨论】:

          【解决方案5】:

          假设日期是连续的,join 完全符合您的要求:

          select t.*, tprev.total as prev_total
          from t join
               t tprev
               on tprev.code = t.code and tprev.date = t.date - interval 1 day;
          

          lag() 在 MySQL 8+ 中也是可能的。使用正确的索引,我不知道哪个会更快。

          【讨论】:

            猜你喜欢
            • 2015-07-26
            • 1970-01-01
            • 1970-01-01
            • 2013-12-15
            • 2011-04-05
            • 1970-01-01
            • 2021-10-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多