简体   繁体   English

mysql查询找到按时间变化分组的字段总和

[英]mysql query to find sum of fields grouping by time change

I have the following data structure 我有以下数据结构

  timestamp(varchar)    bid(decimal) ask(decimal) 
20090501 03:01:01.582   0.000060    0.000000
20090501 15:01:01.582   0.000120    0.000060
20090501 16:01:01.582   -0.000080   0.000120
20090504 03:01:01.582   0.000040    0.000060
20090504 15:01:01.582   -0.000040   0.000040
20090504 16:01:01.582   0.000000    -0.000040
20090505 03:01:01.582   0.000050    0.000110
20090505 15:01:01.582   0.000000    0.000050
20090505 16:01:01.582   -0.000080   0.000000

Now I want the output like the following 现在我想要类似以下的输出

timestamp   sum (bid)   sum(ask)
20090501 15:01:01.582   0.000180    0.000060

20090504 15:01:01.582   -0.000080   0.000220


20090505 15:01:01.582   0.000050    0.000120

Now the relational logic behind the result is every time 15:01 occurs it will sum all the bids and asks value within the interval of last 15:01 occurrence it means the sum of bids and asks between every 15:01 need to be calculated I am trying this with MySQL, so any help on this is highly appreciable. 现在结果背后的关系逻辑是每次15:01发生时,它将在最近15:01发生的间隔内将所有出价和要价求和,这意味着需要计算每15:01之间的出价和要价之和I我正在使用MySQL进行尝试,因此对此的任何帮助都是非常可观的。

The code which I have done so far is on Sql server 2008 R2 到目前为止,我完成的代码在Sql Server 2008 R2上

select date=case when substring(timestamp,10,2) <= 15
then substring(timestamp,1,8) else DATEADD("dd",1,substring(timestamp,1,8)) end,
SUM(isnull([Bid Change],0)), SUM([Ask Change]), MAX(aveg),MIN(aveg)  from tbltestnew1 
group by (case when substring(timestamp,10,2) <= 15
then substring(timestamp,1,8) else DATEADD("dd",1,substring(timestamp,1,8)) end),
CURR;

This gives me the result considering 1 day interval of every 15:01 which is not the correct result! 考虑到每15:01间隔1天,这给我的结果是不正确的!

select 
case when time(timestamp) > '15:01:00' 
     THEN DATE(DATE_ADD(timestamp INTERVAL 1 DAY))
     ELSE DATE(timestamp) END AS count_date,
SUM(isnull([Bid Change],0)), 
SUM([Ask Change]), 
MAX(aveg),
MIN(aveg)  from tbltestnew1 
group by count_date;

With MSSQL you could use an outer apply like this: 使用MSSQL,您可以使用outer apply如下所示:

select
  cast(t.timestamp as date) date, 
  bid_sum, 
  ask_sum
from tbltestnew1 t
outer apply (
    select top 1 timestamp tlag 
    from tbltestnew1 
    where t.timestamp > timestamp and cast(timestamp as time) = '15:01:01.582' order by timestamp desc
) tprev
outer apply (
  select sum(bid) bid_sum, sum(ask) ask_sum 
  from tbltestnew1 
  where (tlag is not null and (cast(timestamp as datetime) between dateadd(second,1, tlag) and t.timestamp)
     or (tlag is null and cast(timestamp as datetime) <= t.timestamp)
    )
) x
where cast(t.timestamp as time) = '15:01:01.582';

Sample SQL Fiddle 示例SQL提琴

This query would give this result: 该查询将给出以下结果:

|       DATE |  BID_SUM | ASK_SUM |
|------------|----------|---------|
| 2009-05-01 |  0.00018 | 0.00006 |
| 2009-05-04 | -0.00008 | 0.00022 |
| 2009-05-05 |  0.00005 | 0.00012 |

With MSSQL 2012+ you could have used the lag() window function to access previous rows (which is what the first outer apply does), it would look like this: 使用MSSQL 2012+,您可能已经使用lag()窗口函数来访问先前的行(这是第一个外部应用程序执行的操作),它看起来像这样:

select cast(t.timestamp as date) date, sum_bid, sum_ask
from (select timestamp, ask, bid, lag(timestamp) over (order by timestamp) prev from tbltestnew1 
where cast(timestamp as time) = '15:01:01.582') t
outer apply (
    select sum(bid) sum_bid, sum(ask) sum_ask 
    from tbltestnew1 
    where (prev is not null and (cast(timestamp as datetime) between dateadd(second,1, prev) and t.timestamp)
       or (prev is null and cast(timestamp as datetime) <= t.timestamp))
) oa

Of course you could reduce the number of casts by using a common table expression (or derived tables). 当然,您可以通过使用公用表表达式(或派生表)来减少强制类型转换的次数。

根据您的样本数据,它似乎和GROUP BY LEFT(timestamp, 8)一样简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM