停止查询跳过空值

时间:2014-02-04 01:01:40

标签: mysql sql null aggregate-functions

我有一个查询,显示我应用中过去14天内每天的通话次数。

查询:

SELECT count(id) as count, DATE(FROM_UNIXTIME(timestamp)) as date FROM calls GROUP BY DATE(FROM_UNIXTIME(timestamp)) DESC LIMIT 14

在有0个电话的日子里,此查询不显示那些日期。我不想跳过那些日子,而是希望在那个地方有一个0NULL

关于如何实现这一目标的任何想法?如果您对我的要求有任何疑问,请告诉我。

由于

2 个答案:

答案 0 :(得分:1)

创建一个表,其中包含要确保在结果中的每个日期的行,左外连接与当前查询的结果,使用临时表的日期,上述查询的计数,如果该计数为空,则为0

答案 1 :(得分:1)

我不相信您的查询是“跳过NULL值”,正如您的标题所暗示的那样。相反,您的数据可能看起来像这样:

 id | timestamp
----+------------
  1 | 2014-01-01
  2 | 2014-01-02
  3 | 2014-01-04

因此,没有包含缺少日期的行,因此没有要计算的行。答案是您需要生成所需日期的列表,然后对其进行LEFTRIGHT JOIN

不幸的是,MySQL并没有像其他数据库一样简单。似乎没有一种生成任何内联列表的有效方法。所以你需要某种表格。

我想我会创建一个静态表,其中包含一组要从当前日期中减去的整数。然后,您可以使用此表生成内联日期列表和JOIN到它。

CREATE TABLE days_ago_list (days_ago INTEGER);

INSERT INTO days_ago_list VALUES
 (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13)
;

然后:

SELECT COUNT(id), list_date
FROM (SELECT SUBDATE(CURDATE(), days_ago) AS list_date FROM days_ago_list) dates_to_list
LEFT JOIN (SELECT id, DATE(FROM_UNIXTIME(timestamp)) call_date FROM calls) calls_with_date
     ON calls_with_date.call_date = dates_to_list.list_date
GROUP BY list_date

list_date分组非常重要;对于没有通话的任何日期,call_date将为NULLCOUNT上的id也很重要,因为NULL id不会被计算在内。 (这可确保您在没有呼叫的情况下获得正确的0计数。)如果您需要更改列出的日期,只需更新包含整数列表的表。

Here is a SQL Fiddle证明了这一点。

或者,如果这是针对Web应用程序的,则可以生成日期代码端列表,并将计数与查询完成后的日期进行匹配。这会使您的Web应用程序逻辑变得更复杂,但它也会简化查询并消除对额外表的需求。