SQL Group按日期

时间:2016-01-06 12:47:45

标签: mysql sql group-by

好的,我有一个表,其中包括列:name,c_id,date。

该表中的某些条目遵循某个条件,我可以使用WHERE有效地选择,因此这不是问题。

然后,除了名称和c_id列之外,我还希望将三个日期的分组:日期 - 1,日期和日期+ 1。换句话说,我希望输出的每一行代表所有具有相同名称的条目,c_id代表某个相关条目,并且发生在该条目的前一天和后一天之间,包括其自身。

我将如何做到这一点?

- 编辑:

(EDIT2:原始表应该是Table1的INNER JOIN,Table2是Table1.id = Table2.id)

示例数据:

Table1:
  id  |  c_id  |     date     |  other stuff
-----------------------------------------------------
  01  |  abc   |  2015/12/09  |  whatever
  02  |  abc   |  2015/12/09  |  whatever
  03  |  abc   |  2015/12/10  |  relevant criterion
  04  |  abc   |  2015/12/11  |  whatever
  05  |  def   |  2015/11/15  |  whatever
  06  |  def   |  2015/11/16  |  relevant criterion
  07  |  abc   |  2015/11/17  |  whatever
  08  |  mnc   |  2016/01/02  |  whatever
  09  |  mnc   |  2016/01/02  |  whatever
  10  |  mnc   |  2016/01/03  |  whatever
  11  |  mnc   |  2016/01/03  |  whatever
  12  |  mnc   |  2016/01/03  |  whatever
  13  |  mnc   |  2016/01/04  |  relevant criterion
  14  |  mnc   |  2016/01/05  |  whatever
  15  |  mnc   |  2016/01/05  |  whatever
  16  |  mnc   |  2016/01/06  |  whatever

Table2:
  id  |  Name  |  other stuff
--------------------------------------
  01  |  John  |  whatever
  02  |  John  |  whatever
  03  |  John  |  whatever
  04  |  John  |  whatever
  05  |  Mary  |  whatever
  06  |  Mary  |  whatever
  07  |  Mary  |  whatever
  08  |  Alice |  whatever
  09  |  Alice |  whatever
  10  |  Alice |  whatever
  11  |  Alice |  whatever
  12  |  Alice |  whatever
  13  |  Alice |  whatever
  14  |  Alice |  whatever
  15  |  Alice |  whatever
  16  |  Alice |  whatever

示例所需的输出:

  Name  |  c_id  |  pivot_date  |  count
------------------------------------------
  John  |  abc   |  2015/12/10  |  4
  Mary  |  def   |  2015/11/16  |  2
  Alice |  mnc   |  2016/01/04  |  6

(pivot_date部分不一定特别是具有相关标准的部分,所涉及的任何一个日期都是好的。)

4 个答案:

答案 0 :(得分:0)

更新了新的样本数据:

  SELECT t.name, t.c_id, t.date pivot_date, COUNT(*) count
    FROM record t
    JOIN record t2
      ON t2.name = t.name
     AND t2.c_id = t.c_id
     AND t2.date >= t.date - INTERVAL 1 DAY        
     AND t2.date <= t.date + INTERVAL 1 DAY
   WHERE t.other_stuff = 'relevant criterion'
GROUP BY t.name, t.c_id, t.date

See SQLFiddle

-

更新了新的样本数据:

  SELECT t2.name, t1.c_id, t1.date pivot_date, COUNT(*) count
    FROM table1 t1
    JOIN table1 to1
      ON to1.c_id = t1.c_id
     AND to1.date >= t1.date - INTERVAL 1 DAY        
     AND to1.date <= t1.date + INTERVAL 1 DAY
    JOIN table2 
      ON t2.id = t1.id
   WHERE t1.other_stuff = 'relevant criterion'
GROUP BY t2.name, t1.c_id, t1.date

答案 1 :(得分:0)

这是一种方式:

@dt := '2015-12-10'

SELECT Name , c_id, MAX(`date`) maxdate, COUNT(*) countof
FROM table1
WHERE date >= @dt - INTERVAL 1 DAY  AND `date` < @dt  + INTERVAL 2 DAY
GROUP BY Name , c_id

请注意,日期列可以是MIN(日期)作为替代

答案 2 :(得分:0)

我必须使用分析LAG / LEAD函数在Oracle中构建它。我不知道你是否可以在MYSQL中模拟这些函数(看here进行模拟)

table1是您的数据

with 
relevant as
(
select *
  from (
    select 
      nm,
      c_id,
      stuff,
      dt,
      lag(dt,1) over ( order by nm, dt, c_id) prev,
      lead(dt,1) over ( order by nm, dt, c_id) nxt
    from table1 )
where stuff = 'relevant criterion'
)
select 
    d.nm,
    d.c_id,
    to_char(d.dt,'DD-MON-YYY') dt,
    d.stuff,
    count(*) over (partition by d.nm, d.c_id) cnt
  from table1 d
where ( d.dt in ( select rp.prev from relevant rp where d.nm = rp.nm and d.c_id = rp.c_id ) 
        OR
        d.dt in ( select rn.nxt from relevant rn where d.nm = rn.nm and d.c_id = rn.c_id  )
        OR
        d.dt in ( select rn.dt from relevant rn where d.nm = rn.nm and d.c_id = rn.c_id  )
      )
;

结果:

NM  C_ID    DT  STUFF   CNT
Alice   mnc 03-JAN-016  whatever    6
Alice   mnc 03-JAN-016  whatever    6
Alice   mnc 03-JAN-016  whatever    6
Alice   mnc 05-JAN-016  whatever    6
Alice   mnc 04-JAN-016  relevant criterion  6
Alice   mnc 05-JAN-016  whatever    6
John    abc 11-DEC-015  whatever    4
John    abc 10-DEC-015  relevant criterion  4
John    abc 09-DEC-015  whatever    4
John    abc 09-DEC-015  whatever    4
Mary    def 15-NOV-015  whatever    2
Mary    def 16-NOV-015  relevant criterion  2

您可以通过将此查询创建为视图并添加where stuff = 'relevant criterion'过滤条件

来过滤上述结果
NM  C_ID    DT  STUFF   CNT
Alice   mnc 04-JAN-016  relevant criterion  6
John    abc 10-DEC-015  relevant criterion  4
Mary    def 16-NOV-015  relevant criterion  2

答案 3 :(得分:0)

这是一种天真的方式。它有点工作:

select t2.Name, t1.c_id, min(t1.Date) as pivot_date, count(*) as cnt
from Table1 t1 inner join Table2 t2 on t2.id = t1.id
where <criteria...>
group by t2.Name, t1.c_id, datediff(t1.Date, '2015-01-01') div 3

这种方法根据起点任意将日历划分为三天。

可以有连续的日期,形成第一个区块的结尾和下一个区块的开始。我怀疑你是否想要那个,我会看到我是否能找到能够提供更好平衡的东西。

您遗漏的过滤条件有多复杂?