sql计数行

时间:2009-10-27 03:36:23

标签: sql mysql

我在MySQL中有以下表格......

CREATE TABLE `visits` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `visit` datetime NOT NULL default '0000-00-00 00:00:00',
  `bulletin` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) 

“访问”是指访问的时间,“公告”是当时要求的文章。

我想知道我的用户受欢迎的时间,所以我有以下查询......

SELECT 
    count(*) as c, 
    Date_format (visit, '%l%p, %e %b %Y') as e
FROM 
    `visits`
WHERE 1
AND 
    date(visit) > date(now() - interval 2 day)
group by e
order by visit desc

返回......

c   e  
4   12PM, 27 Oct 2009  
9   11AM, 27 Oct 2009  
5   10AM, 27 Oct 2009  
2   9AM, 27 Oct 2009  
3   4PM, 26 Oct 2009  
6   3PM, 26 Oct 2009  
16  2PM, 26 Oct 2009  

到目前为止一切顺利。

但是如何让查询返回“0”表示计数和缺少时间的时间?例如,我希望结果看起来像......

c   e  
4   12PM, 27 Oct 2009  
9   11AM, 27 Oct 2009  
5   10AM, 27 Oct 2009  
2   9AM, 27 Oct 2009
0   8AM, 27 Oct 2009
0   7AM, 27 Oct 2009
0   6AM, 27 Oct 2009
0   5AM, 27 Oct 2009
0   4AM, 27 Oct 2009
0   3AM, 27 Oct 2009
0   2AM, 27 Oct 2009
0   1AM, 27 Oct 2009
0   12am, 27 Oct 2009
0   11pm, 26 Oct 2009
0   10pm, 26 Oct 2009
0   9pm, 26 Oct 2009
0   8pm, 26 Oct 2009
0   7pm, 26 Oct 2009    
0   6pm, 26 Oct 2009  
0   5pm, 26 Oct 2009
3   4PM, 26 Oct 2009  
6   3PM, 26 Oct 2009  
16  2PM, 26 Oct 2009  

当我打印结果时,我可以在输出代码中捏造这个,但如果可能的话,我希望查询为我提供。

4 个答案:

答案 0 :(得分:2)

您应该从所有日期生成的数据集中进行选择。时间,左加入表“访问”。我不太了解MySql,所以我不能给你一个如何生成日期和时间集的例子,但是像这样:

SELECT 
    count(*) as c, 
    Date_format (d.DateTime, '%l%p, %e %b %Y') as e
FROM 
    GetDateSetFunction() d
LEFT JOIN
    `visits` v
    ON Date_format(d.DateTime, '%l%p, %e %b %Y') = Date_format (v.visit, '%l%p, %e %b %Y') 
WHERE 1
AND 
    date(d) > date(now() - interval 2 day)
group by e
order by d.DateTime desc

答案 1 :(得分:1)

  1. 创建一个数字表:

    CREATE TABLE `NUMBERS` (
      `num` int(11) NOT NULL auto_increment,
      PRIMARY KEY  (`num`)
    )
    
  2. 填充表格:

    INSERT INTO NUMBERS VALUES (NULL)
    

    根据您的示例,您需要运行语句~36次。

  3. 使用以下内容:

       SELECT IFNULL(vd.num_visits, 0),
              DATE_FORMAT(s.gdate, '%l%p, %e %b %Y')
         FROM (SELECT DATE_ADD(@min_date, INTERVAL n.num-1 HOUR) 'gdate'
                 FROM NUMBERS n
                WHERE DATE_ADD(@min_date, INTERVAL n.num-1 HOUR) <= @max_date ) s
    LEFT JOIN (SELECT v.visits,
                      COUNT(*) 'num_visits'
                 FROM visits v
             GROUP BY v.visits) vd ON vd.visits = s.gdate
     ORDER BY s.gdate DESC
    
  4. 数字表是一个老技巧,当您无法递归生成值列表时使用。

    如果要根据VISITS表的最小值/最大值使用,请使用:

    FROM (SELECT DATE_ADD(@min_date, INTERVAL n.num-1 HOUR) 'gdate'
            FROM NUMBERS n
            JOIN (SELECT MIN(t.visits) 'minv',
                         MAX(t.visits) 'maxv'
                    FROM visits t) t
           WHERE DATE_ADD(t.minv, INTERVAL n.num-1 HOUR) <= t.maxv ) s
    

答案 2 :(得分:0)

您可能必须在查询中创建假日期才能完成此操作...只需使用一天中的24小时填充数组,然后仅更改查询行循环中的0值。

答案 3 :(得分:0)

你应该可以为所有款项建立联盟。

select count(*) as c, Date_format (visit, '%l%p, %e %b %Y') as e
from table where 
date(visit) > date(now() - interval 2 day) 
and date(visit) < date(now() - interval 2 day + 1 hour)
group by e
union
select count(*) as c, Date_format (visit, '%l%p, %e %b %Y') as e
from table where
date(visit) > date(now() - interval 2 day + 1 hour) 
and date(visit) < date(now() - interval 2 day + 2 hour)
group by e
... #etc
union
select count(*) as c, Date_format (visit, '%l%p, %e %b %Y') as e
from table where
date(visit) > date(now() - interval 2 day + 47 hour) 
and date(visit) < date(now() - interval 2 day + 48 hour)
group by e;

这个想法是你分别抓住每个小时,将它们组合在一起。如果特定时间没有结果,您仍然可以获得0计数。

我对mysql的语法细节不太熟悉,所以我把它们放在一起作为psuedo-sql。我从你的代码中复制了大部分语法,但不知道我是否错过了什么。我还没有测试过这段代码。