MySQL 累计总和按日期分组但在特定日期后排除
MySQL cumulative sum grouped by date but exclude after certain date
我有一个涉及日期的查询非常接近完成,但我不太明白最后一部分。 table 列是:
purchased TINYINT
purchased_date DATE
expired TINYINT
expiration_date DATE
我运行的查询是这样的:
SELECT
e_date,
num_interactions,
@runningTotal := @runningTotal + totals.num_interactions AS runningTotal
FROM
(SELECT
DATE(purchase_date) AS e_date,
COUNT(*) AS num_interactions
FROM domain_names AS d
WHERE purchased = 1
AND purchase_date != "0000-00-00"
GROUP BY DATE(d.purchase_date)) totals
ORDER BY e_date;
它运行良好,但我需要进行最后一次调整。我需要 exclude/subtract 运行 个在 e_date
.
之后过期的名字(基于 expiration date
)
换句话说,如果 运行 总数不应计入过期日期之后的域。非常感谢您在这里提出任何建议。这是我第一次 post 来到这里,希望我已经解释清楚了。
编辑:
我整理了一个 MCRE:
CREATE TABLE IF NOT EXISTS `domain_names` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`purchased` tinyint(1) DEFAULT NULL,
`purchase_date` date DEFAULT NULL,
`expired` tinyint(1) DEFAULT NULL,
`expiration_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_domain_names_on_id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO `domain_names` (`id`, `name`, `purchased`, `purchase_date`, `expired`, `expiration_date`) VALUES
('1', 'example1.com', '1', '2019-01-12', NULL, '2019-08-12'),
('2', 'example2.com', '1', '2019-01-12', NULL, '2020-10-12'),
('3', 'example3.com', '1', '2019-01-12', '1', '2019-10-12'),
('4', 'example4.com', '1', '2019-10-12', NULL, '2020-10-12'),
('5', 'example2.com', '1', '2019-03-19', NULL, '2020-03-19'),
('6', 'example3.com', '1', '2019-08-19', NULL, '2020-08-10'),
('7', 'example4.com', '1', '2019-11-28', NULL, '2020-10-12');
如果您需要排除过期的域,那么您应该将 where 子句 expiration_date > CURDATE()
添加到 couning 子查询或只计算未过期的域 COUNT(case when expiration_date > CURDATE() then 1 end)
...
SET @runningTotal := 0;
SET @runningTotalNE := 0;
SELECT
e_date,
num_interactions,
@runningTotal := @runningTotal + totals.num_interactions AS runningTotal,
@runningTotalNE := @runningTotalNE + totals.notexpired AS runningTotalNotExpired
FROM
(SELECT
purchase_date AS e_date,
COUNT(*) AS num_interactions,
COUNT(case when expiration_date > CURDATE() then 1 end) AS notexpired
FROM domain_names AS d
WHERE purchased = 1
/*AND expiration_date > CURDATE()*/
AND purchase_date != "0000-00-00"
GROUP BY d.purchase_date) totals
ORDER BY e_date
这是一种不依赖变量和子查询的不同方法
SELECT
DATE(d.purchase_date),
COUNT(DISTINCT d.id) AS num_interactions,
COUNT(DISTINCT c.id) AS cumulative_sum_not_expired
FROM domain_names AS d
LEFT JOIN domain_names AS c ON (DATE(c.purchase_date) <= DATE(d.purchase_date)
AND c.purchased = 1
AND c.purchase_date != 0
AND c.expiration_date >= CURDATE())
WHERE d.purchased = 1
AND d.purchase_date != 0
GROUP BY 1
ORDER BY 1;
http://sqlfiddle.com/#!9/2d9f71/36/0
您可以在此处调整排除:
c.expiration_date >= CURDATE()
我有一个涉及日期的查询非常接近完成,但我不太明白最后一部分。 table 列是:
purchased TINYINT
purchased_date DATE
expired TINYINT
expiration_date DATE
我运行的查询是这样的:
SELECT
e_date,
num_interactions,
@runningTotal := @runningTotal + totals.num_interactions AS runningTotal
FROM
(SELECT
DATE(purchase_date) AS e_date,
COUNT(*) AS num_interactions
FROM domain_names AS d
WHERE purchased = 1
AND purchase_date != "0000-00-00"
GROUP BY DATE(d.purchase_date)) totals
ORDER BY e_date;
它运行良好,但我需要进行最后一次调整。我需要 exclude/subtract 运行 个在 e_date
.
expiration date
)
换句话说,如果 运行 总数不应计入过期日期之后的域。非常感谢您在这里提出任何建议。这是我第一次 post 来到这里,希望我已经解释清楚了。
编辑: 我整理了一个 MCRE:
CREATE TABLE IF NOT EXISTS `domain_names` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`purchased` tinyint(1) DEFAULT NULL,
`purchase_date` date DEFAULT NULL,
`expired` tinyint(1) DEFAULT NULL,
`expiration_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_domain_names_on_id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO `domain_names` (`id`, `name`, `purchased`, `purchase_date`, `expired`, `expiration_date`) VALUES
('1', 'example1.com', '1', '2019-01-12', NULL, '2019-08-12'),
('2', 'example2.com', '1', '2019-01-12', NULL, '2020-10-12'),
('3', 'example3.com', '1', '2019-01-12', '1', '2019-10-12'),
('4', 'example4.com', '1', '2019-10-12', NULL, '2020-10-12'),
('5', 'example2.com', '1', '2019-03-19', NULL, '2020-03-19'),
('6', 'example3.com', '1', '2019-08-19', NULL, '2020-08-10'),
('7', 'example4.com', '1', '2019-11-28', NULL, '2020-10-12');
如果您需要排除过期的域,那么您应该将 where 子句 expiration_date > CURDATE()
添加到 couning 子查询或只计算未过期的域 COUNT(case when expiration_date > CURDATE() then 1 end)
...
SET @runningTotal := 0;
SET @runningTotalNE := 0;
SELECT
e_date,
num_interactions,
@runningTotal := @runningTotal + totals.num_interactions AS runningTotal,
@runningTotalNE := @runningTotalNE + totals.notexpired AS runningTotalNotExpired
FROM
(SELECT
purchase_date AS e_date,
COUNT(*) AS num_interactions,
COUNT(case when expiration_date > CURDATE() then 1 end) AS notexpired
FROM domain_names AS d
WHERE purchased = 1
/*AND expiration_date > CURDATE()*/
AND purchase_date != "0000-00-00"
GROUP BY d.purchase_date) totals
ORDER BY e_date
这是一种不依赖变量和子查询的不同方法
SELECT
DATE(d.purchase_date),
COUNT(DISTINCT d.id) AS num_interactions,
COUNT(DISTINCT c.id) AS cumulative_sum_not_expired
FROM domain_names AS d
LEFT JOIN domain_names AS c ON (DATE(c.purchase_date) <= DATE(d.purchase_date)
AND c.purchased = 1
AND c.purchase_date != 0
AND c.expiration_date >= CURDATE())
WHERE d.purchased = 1
AND d.purchase_date != 0
GROUP BY 1
ORDER BY 1;
http://sqlfiddle.com/#!9/2d9f71/36/0
您可以在此处调整排除:
c.expiration_date >= CURDATE()