3

以下是一些用于存储广告活动预算历史记录的表格:

Campaign_budgets_history

id_campaign  budget date
1            10     2013-01-01
1            15     2013-01-03
1            10     2013-01-05

如果某个日期没有数据,则等于上次设置的预算。

如何按日期范围计算预算总和,例如从“2013-01-02”到“2013-01-06”。结果必须是 60 美元,因为“2013-01-02”的预算等于“2013-01-01”,“2013-01-04”的预算等于“2013-01-03” '。

有没有办法通过 SQL 做到这一点?

4

2 回答 2

1

这是给你的一个查询。它使用用户变量来表示查询范围的结束,但在最终版本中,您可能更愿意使用参数占位符。请注意,这是您查询的范围之后@end的第一天,即它是该范围的唯一结束。

SET @begin = '2013-01-02';
SET @end = '2013-01-07';

SELECT
  SUM(DATEDIFF(IF(CAST(c.end AS date) > CAST(@end AS date),
                  CAST(@end AS date),
                  CAST(c.end AS date)
                 ),
               IF(c.begin < CAST(@begin AS date),
                  CAST(@begin AS date),
                  c.begin
                 )
              ) * c.budget
     ) AS overall_budget
FROM
(SELECT a.id_campaign,
        a.date begin,
        MIN(IFNULL(b.date, CAST(@end AS date))) end,
        a.budget
 FROM campaign_budgets_history a
 LEFT JOIN campaign_budgets_history b
        ON a.id_campaign = b.id_campaign AND a.date < b.date
 WHERE a.date < CAST(@end AS date)
 GROUP BY a.id_campaign, a.date
 HAVING end > CAST(@begin AS date)
) c;

在SQL Fiddle上测试。不知道为什么所有的演员都是必要的,也许有一种方法可以避免其中的一些。但是上面的方法似乎有效,而一些演员阵容较少的版本则没有。

这个想法是子查询创建一个范围表,每个范围表示给定预算生效的日期。您可能需要调整第一个范围的开头,以匹配查询范围的开头。然后,您只需减去日期即可获得每个日期的天数,并将该数字乘以每日预算。

于 2013-01-11T10:11:07.897 回答
1

此示例使用日历(实用程序)表...

SELECT * FROM calendar WHERE dt BETWEEN '2012-12-27' AND '2013-01-12';
+------------+
| dt         |
+------------+
| 2012-12-27 |
| 2012-12-28 |
| 2012-12-29 |
| 2012-12-30 |
| 2012-12-31 |
| 2013-01-01 |
| 2013-01-02 |
| 2013-01-03 |
| 2013-01-04 |
| 2013-01-05 |
| 2013-01-06 |
| 2013-01-07 |
| 2013-01-08 |
| 2013-01-09 |
| 2013-01-10 |
| 2013-01-11 |
| 2013-01-12 |
+------------+

SELECT SUM(budget) total
  FROM campaign_budgets_history a
  JOIN 
     ( SELECT MAX(y.date) max_date 
         FROM calendar x 
         JOIN campaign_budgets_history y 
           ON y.date <= x.dt 
        WHERE x.dt BETWEEN '2013-01-02' AND '2013-01-06'
        GROUP
           BY x.dt           
     ) b
    ON b.max_date = a.date;
于 2013-01-11T11:20:19.490 回答