我在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分钟间隔分组的全天销售计数。
发布于 2021-07-25 19:23:27
你可以按照下面的思路做一些事情。如果您还想要多个日期,也可以按salesdate
对查询进行排序,尽管您必须在每个新日期清除整数数组(有关如何执行此操作的信息,请参阅byand
break by`文档)。
ts
变量的计算将取决于十进制值是如何构造的:.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.
发布于 2021-08-06 06:51:09
如果我跳过我关于时间戳是如何构造的问题,您可以使用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中尝试一下。
发布于 2021-07-26 13:18:33
只要每个子查询的效率与一个大查询的效率一样高,那么运行同一查询24次(或任何其他)并没有什么错。
如果你的代码对3年后试图理解你所做的事情的维护程序员来说更加清晰,那么这样做并没有错。
下面的示例只使用了一个日期字段,因为无处不在的"sports“数据库没有任何具有您的示例所具有的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.
https://stackoverflow.com/questions/68518351
复制相似问题