2014-09-19 44 views
0

我需要在本月的第一天到本月的最后一天查找某些数据。这里创建日期序列并将每个日期插入到查询中

select count(*) from q_aggr_data as a 
     where a.filial_='fil1' 
     and a.operator_ like 'unit%' 
     and date_trunc('day',a.s_end_)='"+ date_to_search+ "' 
     group by a.s_name_,date_trunc('day',a.s_end_) 

date_to_searh是01.09.2014,02.09.2014,2014年3月9日,...,2014年9月30日

我已经通过我尝试循环= 0 ... 30,使30查询,但这需要太长时间和非常天真。另外对于没有入口的日子,它应该返回0.我已经看到如何生成日期序列,但不能让我的头脑一个一个一个地注入到查询中

+0

是否有理由不能使用convert/cast + BETWEEN? – ilitirit 2014-09-19 10:57:52

+0

它会计算在几天之内有数据的日期。虽然我需要日期计数行,但在该日期的哪一天,每个月的每一天都是列 – Nazerke 2014-09-19 11:08:39

回答

1

通过创建不仅是一个系列,而是一组的第1天的范围,任何时间戳数据可以使用加入到范围> =与<

特别要注意,这种方法避免了数据上的函数(比如截断日期),并且因此它允许使用索引来帮助查询性能。

如果一些数据是这样的:

CREATE TABLE my_data 
    ("data_dt" timestamp) 
; 

INSERT INTO my_data 
    ("data_dt") 
VALUES 
    ('2014-09-01 08:24:00'), 
    ('2014-09-01 22:48:00'), 
    ('2014-09-02 13:12:00'), 
    ('2014-09-03 03:36:00'), 
    ('2014-09-03 18:00:00'), 

然后可接合,使用outer join所以不匹配的范围仍报告给产生的范围集合(dt_start & dt_end对)

SELECT 
     r.dt_start 
     , count(d.data_dt) 
FROM (
     SELECT 
      dt_start 
      , dt_start + INTERVAL '1 Day' dt_end 
     FROM 
      generate_series('2014-09-01 00:00'::timestamp, 
          '2014-09-30 00:00', '1 Day') AS dt_start 
    ) AS r 
LEFT OUTER JOIN my_data d ON d.data_dt >= r.dt_start 
         AND d.data_dt < r.dt_end 
GROUP BY 
     r.dt_start 
ORDER BY 
     r.dt_start 
; 

并产生如下结果:

|       DT_START | COUNT | 
|----------------------------------|-------| 
| September, 01 2014 00:00:00+0000 |  2 | 
| September, 02 2014 00:00:00+0000 |  1 | 
| September, 03 2014 00:00:00+0000 |  2 | 
| September, 04 2014 00:00:00+0000 |  2 | 
... 
| September, 29 2014 00:00:00+0000 |  0 | 
| September, 30 2014 00:00:00+0000 |  0 | 

See this SQLFiddle demo

0

单程解决这个问题是通过截断日期来分组。

select count(*) 
from q_aggr_data as a 
where a.filial_='fil1' 
and a.operator_ like 'unit%' 
group by date_trunc('day',a.s_end_), a.s_name_; 

另一种方法是使用window function,用于获取计数超过例如截断日期。

0

请检查该查询满足您的要求:

select sum(matched) -- include s_name_, s_end_ if you want to verify the results 
from 
(select a.filial_ 
, a.operator_ 
, a.s_name_ 
, generate_series s_end_ 
, (case when a.filial_ = 'fil1' then 1 else 0 end) as matched 
from q_aggr_data as a 
right join generate_series('2014-09-01', '2014-09-30', interval '1 day') 
    on a.s_end_ = generate_series 
    and a.filial_ = 'fil1' 
    and a.operator_ like 'unit%') aa 
group by s_name_, s_end_ 
order by s_end_, s_name_ 

http://sqlfiddle.com/#!15/e8edf/3