日期范围内的运行总计 - 填写缺失的日期

发布于 2025-01-07 12:57:22 字数 440 浏览 1 评论 0原文

我有下表。

DATE  | AMT
10/10 | 300
12/10 | 300
01/11 | 200
03/11 | 100

我如何获得每月总计?像这样的结果 -

DATE | TOT
1010 | 300
1110 | 300
1210 | 600 
0111 | 800
0211 | 800
0311 | 900

类似的 sql 语句

SELECT SUM(AMT) FROM TABLE1 WHERE DATE BETWEEN '1010' AND '0111'

会导致 0111 为 800,但是...

注意 没有日期限制。这是我的困境。如何填充此列而不对所有日期进行循环并同时显示缺失的月份?

I have the following table.

DATE  | AMT
10/10 | 300
12/10 | 300
01/11 | 200
03/11 | 100

How do I get the monthly total? A result like -

DATE | TOT
1010 | 300
1110 | 300
1210 | 600 
0111 | 800
0211 | 800
0311 | 900

A sql statement like

SELECT SUM(AMT) FROM TABLE1 WHERE DATE BETWEEN '1010' AND '0111'

would result in the 800 for 0111 but...

NOTE There is not a date restriction. which is my dilemma. How do I populate this column without doing a loop for all dates and have the missing months displayed as well?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

拒绝两难 2025-01-14 12:57:22

为了满足缺失的月份,请创建一个模板表来连接。

将其视为缓存。只需在数据库中缓存一个日历,而不是循环遍历并填补空白。

您甚至可以将多个日历(月初、周初、银行假日、工作日等)全部合并到一个表中,并带有一堆搜索标志和索引。

你最终会得到类似...

SELECT
  calendar.date,
  SUM(data.amt)
FROM
  calendar
LEFT JOIN
  data
    ON  data.date >= calendar.date
    AND data.date <  calendar.date + INTERVAL 1 MONTH
WHERE
      calendar.date >= '20110101'
  AND calendar.date <  '20120101'
GROUP BY
  calendar.date

编辑

我刚刚注意到OP想要一个运行总计。

这在 SQL 中是可能的,但效率低。原因是一个月的结果不用于计算下个月。相反,必须重新计算整个运行总计。

因此,通常强烈建议您按上述方法计算每月总计,然后使用您的应用程序进行迭代并得出运行总计值。

如果您确实必须使用 SQL 执行此操作,那么会类似于...

SELECT
  calendar.date,
  SUM(data.amt)
FROM
  calendar
LEFT JOIN
  data
    ON  data.date >= @yourFirstDate
    AND data.date <  calendar.date + INTERVAL 1 MONTH
WHERE
      calendar.date >= @yourFirstDate
  AND calendar.date <  @yourLastDate
GROUP BY
  calendar.date

To cater for missing months, create a template table to join against.

Think of it as caching. Rather than looping through and filling gaps, just have a calendar cached in your database.

You can even combine multiple calendars (start of month, start of week, bank holidays, working day, etc) all into one table, with a bunch of search flags and indexes.

You end up with something like...

SELECT
  calendar.date,
  SUM(data.amt)
FROM
  calendar
LEFT JOIN
  data
    ON  data.date >= calendar.date
    AND data.date <  calendar.date + INTERVAL 1 MONTH
WHERE
      calendar.date >= '20110101'
  AND calendar.date <  '20120101'
GROUP BY
  calendar.date

EDIT

I just noticed that the OP wants a running total.

This -is- possible in SQL but it is extremely inefficient. The reason being that the result from one month isn't used to calculate the following month. Instead the whole running-total has to be calculated again.

For this reason It is normally strongly recommended that you calculate the monthly total as above, then use your application to itterate through and make the running total values.

If you really must do it in SQL, it would be something like...

SELECT
  calendar.date,
  SUM(data.amt)
FROM
  calendar
LEFT JOIN
  data
    ON  data.date >= @yourFirstDate
    AND data.date <  calendar.date + INTERVAL 1 MONTH
WHERE
      calendar.date >= @yourFirstDate
  AND calendar.date <  @yourLastDate
GROUP BY
  calendar.date
灰色世界里的红玫瑰 2025-01-14 12:57:22

主要问题是并且还显示缺失的月份吗?
我不知道如何在没有包含要显示的月\年组合的辅助表的情况下执行此操作:

create table table1(
date datetime,
amt int
)
insert into table1 values ('10/10/2010',100)
insert into table1 values ('12/12/2010',200)
insert into table1 values ('01/01/2011',50)
insert into table1 values ('03/03/2011',500)

truncate table #dates
create table #dates(
_month int,
_year int
)
insert into #dates values(10,2010)
insert into #dates values(11,2010) --missing month
insert into #dates values(12,2010)
insert into #dates values(01,2011)
insert into #dates values(02,2011)--missing month
insert into #dates values(03,2011)


select D._month, D._year, sum(amt)
from #dates D left join TABLE1 T on D._month=month(T.date) and D._year=year(T.date)
group by D._month, D._year

the main problem is the and have the missing months displayed as well?
I don't see how to do it with out an aux table containing the combination of month\year to be displayed:

create table table1(
date datetime,
amt int
)
insert into table1 values ('10/10/2010',100)
insert into table1 values ('12/12/2010',200)
insert into table1 values ('01/01/2011',50)
insert into table1 values ('03/03/2011',500)

truncate table #dates
create table #dates(
_month int,
_year int
)
insert into #dates values(10,2010)
insert into #dates values(11,2010) --missing month
insert into #dates values(12,2010)
insert into #dates values(01,2011)
insert into #dates values(02,2011)--missing month
insert into #dates values(03,2011)


select D._month, D._year, sum(amt)
from #dates D left join TABLE1 T on D._month=month(T.date) and D._year=year(T.date)
group by D._month, D._year
手心的海 2025-01-14 12:57:22

您还可以动态生成一个范围,将其值作为间隔传递给 DATE_ADD,并基本上投影一系列月份值。

正如@Dems所说,您需要有一个相关子查询来计算运行总计,这将非常低效,因为它将在内部运行嵌套循环。

要了解如何生成序列,请查看我的帖子:
如何在Mysql中生成一系列数字

最终查询应该如下所示:(顺便说一句,您应该有一个日期列,而不是这个 varchar 混乱)。

/*NOTE: This assumes a derived table (inline view) containing the sequence of date values and their corresponding TOT value*/
SELECT
  DATEVALUES.DateValue,
  (
  SELECT SUM(TABLE1.AMT) FROM TABLE1 WHERE TABLE1.DateValue <= DATEVALUES.DateValue)
  ) AS RunningSubTotal
FROM
  DATEVALUES

或者类似的东西。

You can also generate a range on the fly, pass its value as the interval to DATE_ADD, and basically project a sequence of month values.

As @Dems said, you need to have a correlated subquery calculate the running total, which will be very inefficient, because it will run a nested loop internally.

To see how to generate the sequence, check my post here:
How to generate a range of numbers in Mysql

The end query should look something like this: (Incidentally, you should have a date column, not this varchar mess).

/*NOTE: This assumes a derived table (inline view) containing the sequence of date values and their corresponding TOT value*/
SELECT
  DATEVALUES.DateValue,
  (
  SELECT SUM(TABLE1.AMT) FROM TABLE1 WHERE TABLE1.DateValue <= DATEVALUES.DateValue)
  ) AS RunningSubTotal
FROM
  DATEVALUES

Or something like that.

擦肩而过的背影 2025-01-14 12:57:22
select sum(AMT) from TABLE1 group by Date
select sum(AMT) from TABLE1 group by Date
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文