[英]MySQL count rows in one table based on dates in another table
我试图对表events
中的行进行计数,其中EventDate
列中的日期发生在另一个表customers
给出的两个日期之间。
顾客
ID EventFrom EventTo
-- ---------- -----------
1 2011-01-01 2012-01-01
2 2012-12-10 2013-12-10
3 2010-05-01 2011-05-01
4 2011-01-01 2012-01-01
5 2012-07-30 2013-07-30
6 2011-06-21 2012-06-21
7 2011-06-22 2012-06-22
8 2010-02-19 2011-02-19
活动
ID EventDate
-- ----------
2 1999-01-01
2 2012-12-12
2 2012-12-13
3 1900-01-12
4 2011-02-10
4 2011-02-11
4 2011-02-12
结果
ID EventFrom EventTo Events
-- ---------- ----------- ------
1 2011-01-01 2012-01-01 0
2 2012-12-10 2013-12-10 2
3 2010-05-01 2011-05-01 0
4 2011-01-01 2012-01-01 3
5 2012-07-30 2013-07-30 0
6 2011-06-21 2012-06-21 0
7 2011-06-22 2012-06-22 0
8 2010-02-19 2011-02-19 0
ID 2在events
出现两次,但是第一个日期不在EventTo
和EventFrom
之间,因此不应计入该日期。 ID 4在events
出现3次,并且都在正确的范围内。
我可以做到,但最终会产生非常缓慢的嵌套连接。
SELECT customers.ID
, customers.EventFrom
, customers.EventTo
, IFNULL(e.Events, 0) AS 'Events'
FROM customers
LEFT JOIN (
SELECT events.ID, COUNT(events.ID) AS 'Events'
FROM events
INNER JOIN customers ON customers.ID = events.ID
AND events.EventDate BETWEEN customers.EventFrom AND customers.EventTo
GROUP BY events.ID
) e ON e.ID = customers.ID
我已将EventDate
设置为events
的索引。 我也尝试将EventFrom
和EventTo
设置为索引,但是并没有太大的区别。 而且此查询是较大查询的一部分,因此我为主要部分设置了索引。
我也尝试过这个:
SELECT customers.ID
, customers.EventFrom
, customers.EventTo
, SUM(IF(events.EventDate BETWEEN customers.EventFrom AND customers.EventTo), 1, 0) AS 'Events'
FROM customers
LEFT JOIN events ON events.ID = customers.ID
这也非常慢。 customers
大约有150万行,但查询似乎花费了不合理的长时间。 有没有更好的方法来构造这个?
MySQL 5.5.32模式设置 :
CREATE TABLE CUSTOMERS
(`ID` varchar(2), `EventFrom` varchar(10), `EventTo` varchar(11))
;
INSERT INTO CUSTOMERS
(`ID`, `EventFrom`, `EventTo`)
VALUES
('1', '2011-01-01', '2012-01-01'),
('2', '2012-12-10', '2013-12-10'),
('3', '2010-05-01', '2011-05-01'),
('4', '2011-01-01', '2012-01-01'),
('5', '2012-07-30', '2013-07-30'),
('6', '2011-06-21', '2012-06-21'),
('7', '2011-06-22', '2012-06-22'),
('8', '2010-02-19', '2011-02-19')
;
CREATE TABLE EVENTS
(`ID` int, `EventDate` datetime)
;
INSERT INTO EVENTS
(`ID`, `EventDate`)
VALUES
(2, '1999-01-01 00:00:00'),
(2, '2012-12-12 00:00:00'),
(2, '2012-12-13 00:00:00'),
(3, '1900-01-12 00:00:00'),
(4, '2011-02-10 00:00:00'),
(4, '2011-02-11 00:00:00'),
(4, '2011-02-12 00:00:00')
;
查询1 :
SELECT c.Id, c.EventFrom, c.EventTo, COUNT(e.ID)
FROM CUSTOMERS c
LEFT JOIN EVENTS e ON e.ID = c.ID AND
e.EventDate BETWEEN c.EventFrom AND c.EventTo
GROUP BY c.Id, c.EventFrom, c.EventTo
结果 :
| ID | EVENTFROM | EVENTTO | COUNT(E.ID) |
|----|------------|------------|-------------|
| 1 | 2011-01-01 | 2012-01-01 | 0 |
| 2 | 2012-12-10 | 2013-12-10 | 2 |
| 3 | 2010-05-01 | 2011-05-01 | 0 |
| 4 | 2011-01-01 | 2012-01-01 | 3 |
| 5 | 2012-07-30 | 2013-07-30 | 0 |
| 6 | 2011-06-21 | 2012-06-21 | 0 |
| 7 | 2011-06-22 | 2012-06-22 | 0 |
| 8 | 2010-02-19 | 2011-02-19 | 0 |
用户已left join
。 将日期条件放在on
子句中。 然后使用count(e.ID)
(计算非NULL值)对表中的匹配项进行count(e.ID)
:
SELECT c.ID, c.EventFrom, c.EventTo,
COUNT(e.ID) as "Events"
FROM customers c LEFT JOIN
events e
ON e.ID = c.ID and
e.EventDate BETWEEN c.EventFrom AND c.EventTo
GROUP BY c.ID, c.EventFrom, c.EventTo;
我宁愿做
select
c.Id,
c.EventFrom,
c.EventTo
COUNT(e.ID)
FROM customers c
LEFT JOIN events e on e.ID = c.ID and e.EvenDate BETWEEN c.EventFrom and c.EventTo
GROUP BY c.Id, c.EventFrom, c.EventTo
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.