获取所有日期以及表

时间:2017-10-29 05:50:24

标签: mysql

我有两张表user_profiletracked_searchuser_profile表包含用户详细信息,tracked_search跟踪每个用户进行的搜索。

每当用户进行搜索时,此搜索条目都会进入tracked_search表。如果在特定日期未搜索任何内容,则tracked_search中不会添加任何内容。

我需要制作一份报告,我需要在每个月的所有日子都显示有多少用户进行了搜索。

例如:

CREATE TABLE tracked_search (
    id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    created DATE,
    user_id int NOT NULL
);

INSERT INTO tracked_search(created, user_id) VALUES
('2017-10-01', 1000),
('2017-10-01', 1000),
('2017-10-01', 2000),
('2017-10-01', 3000),
('2017-10-01', 4000),
('2017-10-04', 1000),
('2017-10-04', 2000),
('2017-10-04', 2000),
('2017-10-04', 2000),
('2017-10-04', 2000),
('2017-10-04', 3000),
('2017-10-31', 1000),
('2017-10-31', 2000),
('2017-10-31', 3000),
('2017-10-31', 4000),
('2017-10-31', 5000);

期望的输出:

Date       user_count 
2017-10-01    4
2017-10-02    0
2017-10-03    0
2017-10-04    3
2017-10-05    0
...
2017-10-30    0
2017-10-31    5

我写了以下查询

SELECT ts.created , count( distinct ts.user_id) FROM tracked_search ts, user_profile u
 WHERE ts.created>=(CURDATE()-INTERVAL 1 MONTH) AND u.id = ts.user_id
 group by ts.created;

但是我得到了

Date       user_count 
2017-10-01    4
2017-10-04    3
2017-10-31    5

如果特定日期没有任何条目,我需要打印所有日期值。它应该为零。

我正在使用MySQL。

3 个答案:

答案 0 :(得分:1)

顺便说一下,你不需要在user_profile上加入。

如果您的dates表格中包含相关日期,则非常简单:

SELECT dates.day AS `Date`, COUNT(DISTINCT ts.user_id) AS user_count
FROM dates
LEFT OUTER JOIN tracked_search AS ts
    ON ts.created = dates.day
GROUP BY dates.day;

由于您可能没有dates表,并且可能不想创建和维护表,因此您可以使用其中一种解决方案来动态生成日期列表。例如Get a list of dates between two datesHow to get list of dates between two dates in mysql select query

SELECT dates.day AS `Date`, COUNT(DISTINCT ts.user_id) AS user_count
FROM (
    SELECT ADDDATE('1970-01-01', t4.i * 10000 + t3.i * 1000 + t2.i * 100 + t1.i * 10 + t0.i) AS day
    FROM (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS t0,
         (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS t1,
         (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS t2,
         (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS t3,
         (SELECT 0 AS i UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS t4
) AS dates
LEFT OUTER JOIN tracked_search AS ts
    ON ts.created = dates.day
WHERE dates.day >= '2017-10-01'
AND dates.day < '2017-11-01'
GROUP BY dates.day;

答案 1 :(得分:0)

您需要在没有AND u.id = ts.user_id的情况下撰写。

SELECT ts.created , count( distinct ts.user_id) FROM tracked_search ts, user_profile u
 WHERE ts.created>=(CURDATE()-INTERVAL 1 MONTH) 
 group by ts.created;

答案 2 :(得分:0)

我能够使用以下逻辑来解决这个问题,希望它可以帮助某人

select 
t1.attempt_date,
coalesce(SUM(t1.attempt_count+t2.attempt_count), 0) AS attempt_count
from
(
  select DATE_FORMAT(a.Date,'%Y/%m/%d') as attempt_date,
  '0' as  attempt_count
  from (
    select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
  ) a
  where a.Date BETWEEN NOW() - INTERVAL 1 MONTH AND NOW()
)t1
left join
(
  SELECT DATE_FORMAT(ts.created,'%Y/%m/%d') AS attempt_date, 
  count( distinct ts.user_id) AS attempt_count
  FROM tracked_search ts, user_profile u
  WHERE ts.user_id = u.id and
  DATE_SUB(ts.created, INTERVAL 1 DAY) > DATE_SUB(DATE(NOW()), INTERVAL 1 MONTH) 
  GROUP BY DAY(ts.created) DESC
)t2
on t2.attempt_date = t1.attempt_date
group by DAY(t1.attempt_date)
order by t1.attempt_date desc;