如何从SQL中获取最近七天的单独总和,其中包含0值

时间:2015-05-08 12:41:33

标签: php mysql

在我的CRM系统中,我有带引线的表格。我想制作一个图表,看看在过去7天内添加了多少潜在客户。为此目的,我需要为上周的每一天提供

我的表tab_leads附带lead_id(整数)和lead_create_date(时间戳,格式:0000-00-00 00:00:00)

所以我需要这样的东西:

  • 第1天至第10天
  • 第2天 - 0
  • 第3天 - 第5天
  • 第4天 - 0
  • 第5天 - 第9天
  • 第6至15天
  • 第7天(今天) - 0

目前我正在使用此查询:

SELECT
    DATE(lead_create_date) AS `Date`,
    COUNT(*) AS `Leads`
FROM
    tab_leads
WHERE
    lead_create_date >=  CURRENT_DATE - INTERVAL 6 DAY
GROUP BY
    DATE(lead_create_date)

但问题是,如果在任何一天我们没有任何数据(例如周末),我得到的金额少于7。实施例

  • 第1天至第10天
  • 第2天 - 第5天
  • 第3天 - 第9天
  • 第4至15天

为了绘制图表,我需要总是七个总和,即使是0值。 如何在MySQL或MySQL + PHP中做到这一点?

..更新: 我只是想创建SQL Fiddle成功。 样本数据:

CREATE TABLE tab_leads (
  `lead_id` int,
  `lead_create_date` timestamp
) ENGINE=InnoDB 

INSERT INTO tab_leads
  (`lead_id`, `lead_create_date`) 
VALUES
(0, '2015-05-02 05:30:40'),
(1, '2015-05-02 00:00:00'),
(2, '2015-05-03 00:00:00'),
(3, '2015-05-03 00:00:00'),
(4, '2015-05-05 00:00:00'),
(5, '2015-05-06 00:00:00'),
(6, '2015-05-07 00:00:00'),
(7, '2015-05-08 00:00:00'),
(8, '2015-05-08 00:00:00')
;

3 个答案:

答案 0 :(得分:2)

不漂亮,但试试这个?

            SELECT tmp.dt, src.Leads
            FROM (
                SELECT CURRENT_DATE - INTERVAL 6 DAY as dt UNION
                    SELECT CURRENT_DATE - INTERVAL 5 DAY UNION
                    SELECT CURRENT_DATE - INTERVAL 4 DAY UNION
                    SELECT CURRENT_DATE - INTERVAL 3 DAY UNION
                    SELECT CURRENT_DATE - INTERVAL 2 DAY UNION
                    SELECT CURRENT_DATE - INTERVAL 1 DAY UNION
                    SELECT CURRENT_DATE) as tmp
                left join (
                    SELECT
                        DATE(lead_create_date ) AS `Date`,
                        COUNT(*) AS `Leads`
                    FROM
                        tab_leads
                    WHERE
                        lead_create_date >=  CURRENT_DATE - INTERVAL 6 DAY
                    GROUP BY


                        DATE(lead_create_date )
                ) as src on tmp.dt = src.`Date`

答案 1 :(得分:2)

这里你的查询是

select 
t1.Date,
coalesce(t2.Leads, 0) AS Leads
from
(
  select DATE_FORMAT(a.Date,'%Y-%m-%d') as Date
  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 curdate() - interval 7 DAY AND curdate()
)t1
left join
(
  SELECT
  DATE(lead_create_date) AS `Date`,
  COUNT(*) AS `Leads`
  from  tab_leads
  WHERE
  lead_create_date >=  CURRENT_DATE - INTERVAL 6 DAY
  GROUP BY DATE(lead_create_date)
)t2
on t2.Date = t1.Date
group by t1.Date
order by t1.Date desc

查询的第一部分只是生成给定范围的日期,然后将其用作左表并对原始查询执行左连接。

从样本数据中,您将获得结果

+------------+-------+
| Date       | Leads |
+------------+-------+
| 2015-05-08 |     2 |
| 2015-05-07 |     1 |
| 2015-05-06 |     1 |
| 2015-05-05 |     1 |
| 2015-05-04 |     0 |
| 2015-05-03 |     2 |
| 2015-05-02 |     2 |
| 2015-05-01 |     0 |
+------------+-------+
8 rows in set (0.02 sec)

答案 2 :(得分:1)

因为在原始表格中没有给定日期的数据,所以您只能返回0行。您可能会看到常见示例,例如:

  

为每个用户提供每个[某个字段]的计数,即使它是0。

这些示例可以完成,假设某个地方的每个user都有一条记录,即使没有some field的记录也是如此。在您的情况下,您没有第2,4或7天的记录,因此无法返回。

要解决此问题,您需要创建过去7天的临时表。使用给定here的示例:

select a.Date 
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 DATE_SUB(NOW(), INTERVAL 7 DAY) and NOW();

这将为您提供所需的临时表。然后,您可以像这样预先形成聚合:

SELECT lead_create_date AS date, COUNT(*) AS numLeads
FROM myTable
GROUP BY lead_create_date;

然后将外部连接到临时表,该表将填充0值:

SELECT tmp.date, COALESCE(m.numLeads, 0) AS numLeads
FROM(
  SELECT a.Date
  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 DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW()) tmp
LEFT JOIN(
  SELECT lead_create_date AS date, COUNT(*) AS numLeads
  FROM myTable 
  GROUP BY lead_create_date) m ON m.date = tmp.date
ORDER BY tmp.date;

它看起来很怪异,但它确实有效。根据其他答案中的评论,它看起来也很好用。

以下是SQL Fiddle示例。

修改

一些澄清,我给出的第一个查询只是为了展示如何创建一个包含最后7个日期的临时表。第二个查询显示如何在整个表上执行聚合以获取表中所有日期的计数。第三个查询将它们组合在一起,仅显示过去七天的计数,这是您正在寻找的答案。