我有一个最新的mysql数据库安装,并且我需要一个函数来计算上个月的第n天到今天之间的销售额。该函数每天将被调用几次,因为我正在寻找自该月前n天以来的累计销售额超过阈值的时间点。
背景是我正在开发一个订阅网站。客户将在一年中的特殊日子进行注册,并全年进行购买。我希望能够按月计算销售额。
如果客户在该月的第n日签约,那么我需要计算该月的前n日与今天之间的销售额。
如果客户在28日签约,而今天是30日签约,那么您会认为只有2天的销售,但是如果今天是3月30日,则有30天。再举一个例子:如果客户在10月31日签约,这将如何处理2月28日或4月30日?
我已经看过诸如timestampdiff()之类的函数,但无法找到实际的解决方案。我的意思是说,一个可以完成工作并可以高效完成任务的人,而不会花费太多的CPU周期。
感谢期待
答案 0 :(得分:0)
您可能正在寻找类似的东西:
DATE_ADD(
LAST_DAY(DATE_SUB(CURDATE(), interval 2 MONTH)),
INTERVAL 15 DAY
)
鉴于天数N
,它返回上个月的第N
天。
从今天开始,如果给定15天,则产生'2018-12-15'
(上个月的15天,例如2018年12月15日)。
如果您要确保返回的日期不会超过上个月的最后一天(例如:当前月份是3月,N = 31
),则可以使用:
LEAST(
DATE_ADD(
LAST_DAY(DATE_SUB(CURDATE(), interval 2 MONTH)),
INTERVAL 15 DAY),
LAST_DAY(DATE_SUB('CURDATE(), interval 1 MONTH))
)
通常是这样:
SELECT LEAST(
DATE_ADD(
LAST_DAY(DATE_SUB('2018-03-28', interval 2 MONTH)),
INTERVAL 31 DAY),
LAST_DAY(DATE_SUB('2018-03-28', interval 1 MONTH))
)
收益:'2018-02-28'
-(二月的最后一天)。
答案 1 :(得分:0)
我可以推荐TIMESTAMP和INTERVAL。它简单高效,无需尝试做一些琐碎的事情
因此请考虑以下架构并进行查询
DROP TABLE IF EXISTS `example_sales`;
CREATE TABLE `example_sales`(
`id` INT(11) UNSIGNED AUTO_INCREMENT,
`id_customer` MEDIUMINT(8) UNSIGNED NOT NULL,
`profits` DECIMAL(16,2) NOT NULL DEFAULT 0,
`ts` TIMESTAMP NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
-- add some values, it doesn't matter the order in the example
INSERT INTO `example_sales`( `id_customer`, `profits`, `ts` ) VALUES
( 1, 10.00, NOW( ) - INTERVAL 12 DAY ),
( 1, 14.00, NOW( ) - INTERVAL 1 WEEK ),
( 1, 110.00, NOW( ) - INTERVAL 30 DAY ),
( 1, 153.00, NOW( ) - INTERVAL 8 DAY ),
( 1, 5.00, NOW( ) - INTERVAL 2 DAY ),
( 1, 97.00, NOW( ) - INTERVAL 13 DAY ),
( 1, 1.00, '2018-02-28 13:00:00' ),
( 1, 2.00, '2018-03-28 13:00:00' ),
( 1, 3.00, '2018-01-30 13:00:00' ),
( 1, 4.00, '2018-03-30 13:00:00' ),
( 1, 42.00, NOW( ) - INTERVAL 42 DAY );
已更新,因为我最初并不完全理解该问题。不过,我保留了时间戳,并做了一些我之前没有注意到的更正。
-- '2018-03-28' or '2018-03-29' instead of NOW( ) or anything you like
SET @last := DATE( NOW( ) );
SET @first := LEAST( DATE_SUB( @last, INTERVAL 1 MONTH ), LAST_DAY( DATE_SUB( @last, INTERVAL 1 MONTH ) ) );
-- change last and first test different sets
SELECT `profits`, DATE( `ts` ) AS `date`
FROM `example_sales`
WHERE `id_customer` = 1
HAVING `date` BETWEEN @first AND @last
ORDER BY `date`;
当您有足够的信心完成这项工作时
SELECT SUM( `profits` ), DATE( `ts` ) AS `date`
FROM `example_sales`
WHERE `id_customer` = 1
HAVING `date` BETWEEN @first AND @last;
希望这次可以解决问题。
答案 2 :(得分:0)
感谢你们俩的贡献。我已经花了几个小时研究这个问题,并且一些最有希望的答案来自stackoverflow,这就是为什么我想在这里发布我的问题。
我同意,这个问题花了很多时间来试图解决问题,所以病态复杂。结果,我将把问题变成容易解决的问题。
我将不再依赖订阅日期,而是基于日历月。这迫使其他地方发生变化,但我想我可以忍受它们。
再次感谢