我可以推荐 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;
希望这一次能解决问题。