如何以 30 分钟为间隔对 24 小时数据进行分组以获取计数?

问题描述

我在 sales 表中有一个字段名称 timestamp,其中数据格式为:20210725.1800,表示 2021 年 07 月 25 日 00:30:00 AM。

现在,如果我想计算从 20210725.0000 到 20210725.1800 之间的 30 分钟间隔内的销售额,我可以简单地编写:

def var k as int no-undo.

for each sales no-lock 
   where salesdate =  07/25/2021 
   and   timestamp >= 20210725.0000
   and   timestamp <= 20210725.1800
:

   if available sales then do:

      k = k + 1.
      pause 0.

      display k with frame f.

   end.

end.

但是,我不想通过更改 timestamp 字段的开始和结束时间来运行相同的查询 24 次。

因此,我正在寻找一种更智能的方法来找出在此时间戳字段上按 30 分钟间隔分组的全天销售计数。

解决方法

您可以按照以下方式做一些事情。如果您也想要多个日期,您也可以按 salesdate 对查询进行排序,尽管您必须在每个新日期清除整数数组(请参阅 byandbreak by` 文档了解如何这样做)。

ts 变量的计算将取决于十进制值的构造方式:0.1800 和 .18002 是否在同一个 30 分钟时段内?

def var numSales as integer extent 24 no-undo.
def var k as integer no-undo.
def var ts as integer.

for each sales 
 no-lock 
   where salesdate eq 07/25/2021:

    // get the timestamp for the day
    // this could use a calculation like the below,// or a simple CASE statement
    ts = 10000 * (timestamp - decimal(string(year(salesdate)) + string(month(salesdate)) + string(day(salesdate)))).

    // find the 30-minute slot. +1 makes it a 'ceiling'
    numSales[integer(ts / (30 * 60)) + 1] += 1.
end.

do k = 1 to 24 with frame f:
    displ
       k (k * 30 * 60) numsales[k].
end.    
,

运行相同的查询 24 次(或其他)确实没有任何问题,只要每个子查询与一个大查询一样有效。

如果它能让 3 年后的维护程序员更清楚地了解您的代码,那么这样做并没有错。

以下示例仅使用 DATE 字段,因为无处不在的“体育”数据库没有您的示例具有的 date.time 样式的任何字段,但应该很容易推断:

const user = [{
    name: 'mahadev',age: 25
  },{
    name: 'roshan',age: 25
  }
];
const n = 'name';
console.log(user[0].n);
,

如果我跳过关于时间戳是如何构建的问题,您可以使用 break by 来获得结果:

def temp-table ttsales no-undo
   field salesdate as date
   field timestamp as decimal
   .

function createSale returns logical (
   i_detimestamp as decimal
):

   def buffer busale for ttsales.

   def var idate  as int.
   def var iyear  as int.
   def var imonth as int.
   def var iday   as int.

   assign
      idate  = truncate( i_detimestamp,0 )
      iyear  = truncate( idate / 10000,0 )
      idate  = idate - iyear * 10000
      imonth = truncate( idate / 100,0 )
      iday   = idate - imonth * 100      
      .

   create busale.
   assign
      busale.salesdate = date( imonth,iday,iyear )
      busale.timestamp = i_detimestamp
      .

end function.

createSale( 20210725.0000 ).
createSale( 20210725.0001 ).
createSale( 20210725.1799 ).
createSale( 20210725.1800 ).
createSale( 20210725.1801 ).

def buffer busale for ttsales.

def var irecords as int.
def var idate    as int.

for each busale
   where busale.salesdate = 07/25/2021
break 
   by truncate( busale.timestamp * 10000 / 1800,0 )
:

   irecords = irecords + 1.

   if last-of( truncate( busale.timestamp * 10000 / 1800,0 ) ) then do:
      display 
         int( truncate( ( ( busale.timestamp * 10000 ) modulo 10000 ) / 1800,0 ) )
         irecords
         .
      irecords = 0.
   end.

end.

ABLdojo 中试用。