【问题标题】:Calculate number of records per value per month, given a table of id, date, and value where the dates are not always consistent给定一个包含 id、日期和值的表,其中日期并不总是一致,计算每个值每月的记录数
【发布时间】:2017-08-15 08:33:25
【问题描述】:

好的,所以我有两张桌子。

locations:

+----+-----------+
| id |   name    |
+----+-----------+
|  1 | Location1 |
|  2 | Location2 |
|  3 | Location3 |
+----+-----------+

location_ratings
+----+-------------+-----------+--------+
| id | location_id |   date    | rating |
+----+-------------+-----------+--------+
|  1 |           1 | 4/7/2017  |      1 |
|  2 |           1 | 7/3/2017  |      2 |
|  3 |           1 | 9/9/2017  |      5 |
|  4 |           1 | 11/2/2017 |      4 |
|  5 |           2 | 1/3/2017  |      3 |
|  9 |           2 | 3/7/2017  |      1 |
| 12 |           3 | 2/7/2017  |      2 |
| 13 |           3 | 3/4/2017  |      4 |
| 15 |           3 | 10/1/2017 |      1 |
+----+-------------+-----------+--------+

地点会随机获得评分,并且会一直保持该评分,直到再次评分。尚未评级的位置的评级被视为 0。因此,对于 Location1,它在 2001 年 4 月 7 日之前为 0,然后在 7 月 3 日之前为 1,依此类推。

我需要计算每个月每个评分的位置数,其中该月的位置评分是该月第一天的评分。

所以基本上我想在每个月的第一天找到每个农场的评级。因此,使用上面的示例数据,这将是每个农场在每个月的第一天的评分:

+---------------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+-----------+-----------+-----------+
| Location ID / Month | 1/1/2017 | 2/1/2017 | 3/1/2017 | 4/1/2017 | 5/1/2017 | 6/1/2017 | 7/1/2017 | 8/1/2017 | 9/1/2017 | 10/1/2017 | 11/1/2017 | 12/1/2017 |
+---------------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+-----------+-----------+-----------+
|                   1 |        0 |        0 |        0 |        0 |        1 |        1 |        1 |        2 |        2 |         5 |         5 |         5 |
|                   2 |        0 |        3 |        3 |        1 |        1 |        1 |        1 |        1 |        1 |         1 |         1 |         1 |
|                   3 |        0 |        0 |        2 |        4 |        4 |        4 |        4 |        4 |        4 |         4 |         1 |         1 |
+---------------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+-----------+-----------+-----------+

然后这将是最终结果(每月每个评级的位置数):

+----------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+-----------+-----------+-----------+
| Rating / Month | 1/1/2017 | 2/1/2017 | 3/1/2017 | 4/1/2017 | 5/1/2017 | 6/1/2017 | 7/1/2017 | 8/1/2017 | 9/1/2017 | 10/1/2017 | 11/1/2017 | 12/1/2017 |
+----------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+-----------+-----------+-----------+
|              0 |        3 |        2 |        1 |        1 |        0 |        0 |        0 |        0 |        0 |         0 |         0 |         0 |
|              1 |        0 |        0 |        0 |        1 |        2 |        2 |        2 |        1 |        1 |         1 |         2 |         2 |
|              2 |        0 |        0 |        1 |        0 |        0 |        0 |        0 |        1 |        1 |         0 |         0 |         0 |
|              3 |        0 |        1 |        1 |        0 |        0 |        0 |        0 |        0 |        0 |         0 |         0 |         0 |
|              4 |        0 |        0 |        0 |        1 |        1 |        1 |        1 |        1 |        1 |         1 |         0 |         0 |
|              5 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |        0 |         1 |         1 |         1 |
+----------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+-----------+-----------+-----------+

所以我正在尝试找出获得最终结果的最佳方法。不确定我是否基本上可以在查询中完成所有操作,或者在提取所有数据后是否需要进行一些计算(我正在使用 Postgres 和 Ruby on Rails)。我还应该提到我(最终)需要不仅能做到这一点,而且能做到周、季和年。任何建议将不胜感激,谢谢!

【问题讨论】:

    标签: ruby-on-rails postgresql dateinterval


    【解决方案1】:

    这是一种方法。这不包括您的表具有的零记录。最简单的方法是确保它们在基础数据中得到体现。

    create table location_ratings as select * from ( values
        (1, 1, '2017-4-7'::date, 1),
        (2, 1, '2017-7-3'::date, 2),
        (3, 1, '2017-9-9'::date, 5),
        (4, 1, '2017-11-2'::date, 4),
        (5, 2, '2017-1-3'::date, 3),
        (9, 2, '2017-3-7'::date, 1),
        (12, 3, '2017-2-7'::date, 2),
        (13, 3, '2017-3-4'::date, 4),
        (15, 3, '2017-10-1'::date, 1)
    ) as t(id, location_id, date, rating);
    
    with months as (
        select generate_series(date_trunc('month', min("date")), 
                               date_trunc('month', max("date")+'1 month'::interval),
                               '1 month') as mon
        from location_ratings
    ),
    month_ratings as (
        select distinct on (l.location_id, m.mon)
            m.mon, l.location_id, l.rating, l.date as rating_date 
        from months m
        left join location_ratings l on m.mon >= l.date
        where l.location_id is not null
        order by l.location_id, m.mon, l.date desc
    )
    --select * from month_ratings;
    select mon, rating, count(*)
    from month_ratings
    group by 1,2 order by 1 asc,2 asc;
    

    month_ratings 结果为:

        mon         location_id rating  rating_date
    1   01.05.2017 00:00:00 1   1   07.04.2017 00:00:00
    2   01.06.2017 00:00:00 1   1   07.04.2017 00:00:00
    3   01.07.2017 00:00:00 1   1   07.04.2017 00:00:00
    4   01.08.2017 00:00:00 1   2   03.07.2017 00:00:00
    5   01.09.2017 00:00:00 1   2   03.07.2017 00:00:00
    6   01.10.2017 00:00:00 1   5   09.09.2017 00:00:00
    7   01.11.2017 00:00:00 1   5   09.09.2017 00:00:00
    8   01.12.2017 00:00:00 1   4   02.11.2017 00:00:00
    9   01.02.2017 00:00:00 2   3   03.01.2017 00:00:00
    10  01.03.2017 00:00:00 2   3   03.01.2017 00:00:00
    11  01.04.2017 00:00:00 2   1   07.03.2017 00:00:00
    12  01.05.2017 00:00:00 2   1   07.03.2017 00:00:00
    13  01.06.2017 00:00:00 2   1   07.03.2017 00:00:00
    14  01.07.2017 00:00:00 2   1   07.03.2017 00:00:00
    15  01.08.2017 00:00:00 2   1   07.03.2017 00:00:00
    16  01.09.2017 00:00:00 2   1   07.03.2017 00:00:00
    17  01.10.2017 00:00:00 2   1   07.03.2017 00:00:00
    18  01.11.2017 00:00:00 2   1   07.03.2017 00:00:00
    19  01.12.2017 00:00:00 2   1   07.03.2017 00:00:00
    20  01.03.2017 00:00:00 3   2   07.02.2017 00:00:00
    21  01.04.2017 00:00:00 3   4   04.03.2017 00:00:00
    22  01.05.2017 00:00:00 3   4   04.03.2017 00:00:00
    23  01.06.2017 00:00:00 3   4   04.03.2017 00:00:00
    24  01.07.2017 00:00:00 3   4   04.03.2017 00:00:00
    25  01.08.2017 00:00:00 3   4   04.03.2017 00:00:00
    26  01.09.2017 00:00:00 3   4   04.03.2017 00:00:00
    27  01.10.2017 00:00:00 3   1   01.10.2017 00:00:00
    28  01.11.2017 00:00:00 3   1   01.10.2017 00:00:00
    29  01.12.2017 00:00:00 3   1   01.10.2017 00:00:00
    

    http://rextester.com/YFNUD43648

    最后:

        mon            rating   count
    1   01.02.2017 00:00:00 3   1
    2   01.03.2017 00:00:00 2   1
    3   01.03.2017 00:00:00 3   1
    4   01.04.2017 00:00:00 1   1
    5   01.04.2017 00:00:00 4   1
    6   01.05.2017 00:00:00 1   2
    7   01.05.2017 00:00:00 4   1
    8   01.06.2017 00:00:00 1   2
    9   01.06.2017 00:00:00 4   1
    10  01.07.2017 00:00:00 1   2
    11  01.07.2017 00:00:00 4   1
    12  01.08.2017 00:00:00 1   1
    13  01.08.2017 00:00:00 2   1
    14  01.08.2017 00:00:00 4   1
    15  01.09.2017 00:00:00 1   1
    16  01.09.2017 00:00:00 2   1
    17  01.09.2017 00:00:00 4   1
    18  01.10.2017 00:00:00 1   2
    19  01.10.2017 00:00:00 5   1
    20  01.11.2017 00:00:00 1   2
    21  01.11.2017 00:00:00 5   1
    22  01.12.2017 00:00:00 1   2
    23  01.12.2017 00:00:00 4   1
    

    http://rextester.com/NYMA93544

    【讨论】:

      猜你喜欢
      • 2021-07-31
      • 2023-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-30
      • 2019-06-23
      • 1970-01-01
      • 2021-05-25
      相关资源
      最近更新 更多