【问题标题】:How to group 24-hour data in 30 minutes interval to get the count?如何以 30 分钟为间隔对 24 小时数据进行分组以获取计数?
【发布时间】:2021-10-01 17:06:38
【问题描述】:

我在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 分钟间隔分组的全天销售计数。

【问题讨论】:

  • 你的数据格式让我很困惑。如果 0.1800 = 00:30,那么 0.9000 = 02:30 - 那么如何记录 03:00?还是应该举例 0.01800 = 00:30 ?

标签: openedge progress-4gl 4gl


【解决方案1】:

您可以按照以下方式进行操作。如果您还想要多个日期,也可以按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.    

【讨论】:

  • 感谢您的回复@nwahmaet。我已在您提供的上述代码中使用 INT64 变量作为数据类型,因为只有 INT 给出错误但现在收到此错误消息** Array subscript -6509 is out of range. (26) ** Array subscript -6508 is out of range. (26) Press space bar to continue. 知道,为什么会这样?
  • 使用新鲜的新闻 += 可能没有启发......
  • 至于“知道发生了什么”,将范围放入一个中间变量中,然后自己弄清楚为什么它被赋予了一个意想不到的值。
  • 更简单的日期时间戳(因为上面看起来不正确):整数(替换(iso-date(salesdate),'-',''))
【解决方案2】:

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

如果这样做可以让 3 年后出现的维护程序员更清楚地了解您所做的事情,那么这样做尤其正确。

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

define variable n as integer no-undo.
define variable d as date    no-undo.

define variable b as handle no-undo.
define variable q as handle no-undo.

create buffer b for table "order".
create query q.
q:set-buffers( b ).

do d = 1/1/1998 to 1/31/1998:

  n = 0.
  q:query-prepare( substitute( 'preselect each order no-lock where orderDate = &1', d )).
  q:query-open no-error.
  if q:query-off-end = no then
    n = q:num-results no-error.
  display d n with frame a down.
  down with frame a.
  q:query-close no-error.

end.

【讨论】:

    【解决方案3】:

    如果我跳过关于您的时间戳是如何构建的问题,您可以使用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 尝试一下。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-05
      • 2016-08-09
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 2023-02-20
      • 2019-09-28
      相关资源
      最近更新 更多