How to calculate yesterday created records with today? - openedge

Hi I would like to know how to calculated records which was created yesterday at some time and calculate with today produced records.
please look my code.
FOR EACH womf_worder OF sfcf_au_ship WHERE womf_worder.word_production_status = "B"
AND womf_worder.word_build_date = DATE(TODAY)
AND womf_worder.word_build_time GE tt_shift.shft_start_hour
AND womf_worder.word_build_time LE tt_shift.shft_stop_hour NO-LOCK:
IF AVAILABLE womf_worder THEN DO:
i = i + 1.
END.
tt_shift.shft_start_hour = 06:00:00 and stop_hour = 23:50:00
Here my question is how can calculate records which will be produced by tomorrow with yesterday records. How can i use DATETIME for this?

DATETIME would be very usable if any field in the database is DATETIME. A quick lock at your example makes me think you have separate date and time fields. I'm unsure what the TIME field is. Perhaps an integer or a string?
You don't need the availability check in a FOR-loop. It's for FINDS and possibly JOINS where a record might not be available in the loop. For a basic FOR EACH like that only available records will be processed.
If the time is indeed an integer or a string your code could very well work with a minor fix for the availability check.
FOR EACH womf_worder OF sfcf_au_ship WHERE womf_worder.word_production_status = "B"
AND womf_worder.word_build_date = DATE(TODAY)
AND womf_worder.word_build_time GE tt_shift.shft_start_hour
AND womf_worder.word_build_time LE tt_shift.shft_stop_hour NO-LOCK:
i = i + 1.
END.

for each womf_worder of sfcf_au_ship where
womf_worder.word_production_status EQ "B" and
womf_worder.word_build_date EQ today - 1 and
womf_worder.word_build_time GE tt_shift.shft_start_hour and
womf_worder.word_build_time LE tt_shift.shft_stop_hour
no-lock:
assign i = i + 1.
end.
Notes:
Function "today" returns a datetype value, dont need casting date();
Use expression "today - 1";
Don't need "if avail" condition for "for each" blocks, if AVM finds any record, it aways avail;

Related

QUERY formula to return only the latest record per email based on timestamp

Having this Google Sheet QUERY formula:
=QUERY(FORMULARIO!A4:Q, " select G,E,K,M,N,L,O,Q where not upper(J) = 'PAGÓ' and A > date '"&TEXTO(HOY()-3, "yyyy-mm-dd")&"' and E is not null and O is not null and Q contains '#' and not Q matches '"&TEXTJOIN("|", 1, QUERY(FORMULARIO!J4:Q, "select Q where upper(J) = 'PAGÓ' ", 0))&"'", 0)
How to return only one record per email (column Q) being the most recent one looking at date which is at column A?
TEST SHEET:
https://docs.google.com/spreadsheets/d/1jBMo42cbylrNHcf9b9QLI4oDw0H0oomCGrEAuPsBlA8/edit#gid=1465616509
Under tab "results" is the working query where i only need to filter out duplicates based on recency, leaving only the most recent one, and the unique identifier being email
EDIT
(following OP's shared demo sheet)
The formula to use would be:
=SORT(SORTN(QUERY(FORMULARIO!A4:Q, " select G,E,K,M,N,L,O,Q where not upper(J) = 'PAGÓ' and A > datetime '"&TEXTO(AHORA()-3, "yyyy-mm-dd HH:mm:ss")&"' and E is not null and O is not null and Q contains '#' and not Q matches '"&TEXTJOIN("|", 1, QUERY(FORMULARIO!J4:Q, "select Q where upper(J) = 'PAGÓ' ", 0))&"'", 1),9^9,2,2,1),1,1)
What was changed:
We wrapped your original query with the SORTN function to find and exclude all duplicate emails from column Q except the most recent one based on the Timestamp from column A.
We -one more time- wrapped the results with the SORT function to have our final results sorted by the Timestamp.
Pro tip
An extra change was also made within the main query by changing
and A > date '"&TEXT(HOY()-3, "yyyy-mm-dd")&"'
to
and A > datetime '"&TEXT(AHORA()-3, "yyyy-mm-dd HH:mm:ss")&"'
So we changed TODAY to NOW.
By doing this we count dates making use of both the date and time present in a timestamp instead of just the date.
(There is still room for minor improvements/alterations but out of the scope of this question.)
Original answer
Taking for granted that your formula works as expected (cannot check it without a test sheet) but produces multiple rows you can use the limit clause in the end of your formula.
=QUERY(FORMULARIO!A4:Q, " select G,E,K,M,N,L,O,Q where not upper(J) = 'PAGÓ' and A > date '"&TEXTO(HOY()-3, "yyyy-mm-dd")&"' and E is not null and O is not null and Q contains '#' and not Q matches '"&TEXTJOIN("|", 1, QUERY(FORMULARIO!J4:Q, "select Q where upper(J) = 'PAGÓ' ", 0))&"' limit 1", 0)

Kusto query - how to get beginning datetime of current month

Learning Kusto query and looking for a way to get beginning of current month datetime.
As of time I post this it is 2/25/2020 so output should looks like below represents Feb 1, 2020
This is what I have so far and works, but there should be better way of doing this.
Can anyone please let me know if this query can be improved?
What's the common practice of getting beginning of current month?
Below, get year and month, add leading 0 if needed for month then concatenate the string and assign to variable "d" which then look like "2020-02-01" and pass that string to todatetime()
let year = datetime_part("Year",now());
let month = datetime_part("Month",now());
let m = case(month < 10, strcat("0", month), tostring(month));
let d = strcat(year, "-", m, "-01" );
print todatetime(d);
Try the startofmonth() function.
Example:
MyKustoTable
| project MonthStart = startofmonth(datetime('2020-2-5'))
Reference: https://learn.microsoft.com/en-us/azure/kusto/query/startofmonthfunction
there's a startofmonth() function: https://learn.microsoft.com/en-us/azure/kusto/query/startofmonthfunction

Complex calculation of the hours amount

I have a Pythonic system that stores student absences data in a SQLite database. Each row includes the start and end time of the absence, represented by the number of seconds since Jan 01 1970. I was asked to add a feature which limits the number of hours of absence per week.
It sounds easy to pull out the amount of hours, using a statement like this:
SELECT (sum(ending-starting)/3600)
FROM requests
WHERE student_id = {x}
AND starting BETWEEN {y} AND ({y}+604800)
AND approved = 1
The problem is that the limit must only be the hours defined as "mandatory presence." For example, if a user has defined the hours 8:00 to 17:00 as a "mandatory presence," an absence that begins on Sunday at 14:00 and ends on Monday at the same time, will be calculated in the code above 24 hours, while in practice it is only 9 hours.
"Mandatory presence" is defined in the database as two numerical parameters: "morning" and "evening" (always a round hour). Is there a way to make the calculation above taking into account these two numbers?
If it can not be done in sql, I would love to hear how to select the data in sql and then perform the calculation in python.
I believe the following may do what you wish :-
SELECT
(
sum((
(ending - starting)
-(
CASE WHEN starting < strftime('%s',date(starting,'unixepoch')||' 08:00')
THEN strftime('%s',date(starting,'unixepoch')||' 08:00') - starting
ELSE 0
END
+
CASE WHEN ending > strftime('%s',date(starting,'unixepoch')||' 17:00')
THEN ending - strftime('%s',date(starting,'unixepoch')||' 17:00')
ELSE 0
END
)
) /3600)
) AS ha, *
FROM requests
WHERE student_id = {x}
AND starting BETWEEN {y} AND ({y}+604800)
AND approved = 1
;
MikeT's answer is not entirely working, but it certainly helped me reach the desired result. Here's the perfect statement:
SELECT
(
sum((
(ending - starting)
-(
CASE WHEN starting < strftime('%s',date(starting,'unixepoch')||printf(' %02d:00', morning))
THEN strftime('%s',date(starting,'unixepoch')||printf(' %02d:00', morning)) - starting
ELSE 0
END
+
CASE WHEN ending > strftime('%s',date(ending,'unixepoch')||printf(' %02d:00', evening))
THEN ending - strftime('%s',date(ending,'unixepoch')||printf(' %02d:00', evening))
ELSE 0
END
)
) /3600.0
-(
(24-evening+morning)
*
(round(julianday(ending, 'unixepoch'))-round(julianday(starting, 'unixepoch')))
)
)) AS ha
FROM requests
INNER JOIN students ON requests.student_id = students.ID
INNER JOIN institutes ON students.inst_id = institutes.ID
WHERE student_id = {x}
AND starting BETWEEN {y} AND ({y}+604800)
AND approved = 1;
Thank you very much for your help!

How to calculate yesterday records with today records using progress 4gl?

I have written a program and i need to calculate yesterday records(timing 12:00 AM to 05:00 AM) with today records
for each womf_worder of sfcf_au_ship where
womf_worder.word_production_status EQ "B" and
womf_worder.word_build_date EQ today - 1 and
womf_worder.word_build_time GE tt_shift.shft_start_hour and
womf_worder.word_build_time LE tt_shift.shft_stop_hour
no-lock:
assign i = i + 1.
end.
But the problem is I need to calculate the orders only on those mentioned time(12:00 AM to 05:00 AM) with today records. Could you please help this case?
If you know your data doesn't have 'future' dates in it, you could use something like this:
for each womf_worder of sfcf_au_ship where
womf_worder.word_production_status EQ "B" and
womf_worder.word_build_date GE today - 1 and
womf_worder.word_build_time GE tt_shift.shft_start_hour and
womf_worder.word_build_time LE tt_shift.shft_stop_hour
no-lock:
assign i = i + 1.
end.
If you are not familiar with the data you are working with or want it to be more portable:
for each womf_worder of sfcf_au_ship where
womf_worder.word_production_status EQ "B" and
womf_worder.word_build_time GE tt_shift.shft_start_hour and
womf_worder.word_build_time LE tt_shift.shft_stop_hour and
( womf_worder.word_build_date eq today - 1 or
womf_worder.word_build_date eq today )
no-lock:
assign i = i + 1.
end.
From what I understand it looks you need to use brackets and an "OR" operator,
so you'll need something like this:
FOR EACH womf_worder OF sfcf_au_ship no-lock
WHERE womf_worder.word_production_status EQ "B"
AND (womf_worder.word_build_date EQ today - 1
AND womf_worder.word_build_time GE tt_shift.shft_start_hour)
OR (womf_worder.word_build_date EQ today
AND womf_worder.word_build_time LE tt_shift.shft_stop_hour)
:
ASSIGN i = i + 1.
END.
Hope this helps.

How to convert string to datetime format classic asp

I have one variable
Dim tt="2008-10-20 10:00:00.0000000"
I want to change it into date,
Try CDATE(tt) see http://www.w3schools.com/vbscript/func_cdate.asp. I used
vbscript cdate
as keywords at Google. There were more results.
Edit: Based on the comment below (I'm sorry for mixing up), using
FormatDateTime(date,format)
Format contains following constants:
0 = vbGeneralDate - Default. Returns date: mm/dd/yy and time if
specified: hh:mm:ss PM/AM.
1 = vbLongDate - Returns date: weekday, monthname, year
2 = vbShortDate - Returns date: mm/dd/yy
3 = vbLongTime - Returns time: hh:mm:ss PM/AM
4 = vbShortTime - Return time: hh:mm
(copied from http://www.w3schools.com/vbscript/func_formatdatetime.asp)
This link, (MS CDate page), explains that:
adate = CDate(astring)
converts a string into a date object. For there, you can format it with the FormatDateTime function
str = FormatDateTime(Date)
the FormatDateTime function is "smart" -- it will format as date and time if both are present, otherwise it will format with whichever of date or time is present.
I propose a safe solution which returns the result only if the conversion is successful:
s="2008-10-20 10:00:00.0000000"
On Error Resume Next
d=CDate(Left(s,19))
On Error Goto 0
if not IsEmpty(d) then MsgBox d
Try it for a non-valid date or non-valid format. The result will be empty.
s="2008-02-31 10:00:00"
In same contexts, it is necessary to initialize the variable collecting result of CData. I recommend to initialize it as Empty. Example below shows such case - counting valid dates in a string array:
Lines = array("2008-10-20 10:00:00.0000000", "2008-10-20 10:00:00", "", "2008-02-31", "Today", "2017-02-7")
On Error Resume Next
Count=0
for each Line in Lines
d=Empty
d=CDate(Line)
if not IsEmpty(d) then Count=Count+1
next
On Error Goto 0
MsgBox "Number of valid dates is "&Count
The correct answer is 2. Without initialization we get 5 as the CDate does not do anything on error so variable keeps the value from a recent iteration in the loop.
If do not need your milliseconds, your could use the following:
<script type="text/vbscript">
s="2008-10-20 10:00:00.0000000"
arr= Split(s, ".")
d=CDate(arr(0))
document.write(d)
</script>
I believe cdate is dependent on local settings to parse the string. This is no good in many situations.
To avoid this you need to use
DateSerial()
and if needed add any time components to the result separately.
The date literal in classic asp is unreliable. If the first or second part is greater than 12, it takes that value for day, the other as month. If both parts are less than 12, the interpretation is unpredictable: sometimes american and sometimes british.
A work-around is to force the entry of dates into separate fields or use a date entry module which can set the date into british or american style.
A date literal should be treated as american and use a function to convert that into a date variable using Dateserial().
function amerdate(str)
'str 3/5/2023 form: in american format: use for calculations including date
Dim d
d = Split(str, "/")
amerdate = Dateserial(d(2), d(0), d(1))
end function
Use only american date in calculations like Dateadd() etc.
someday = "3/5/2023" '5th march, american date literal
nextday = Dateadd("d", 1, amerdate(someday))
Whenever a date display is required, convert to british date and show it.
function britdate(str)
'str: 3/5/2023 form: display in british form. not for calculations
Dim d
d= Split(str, "/")
britdate = d(1) & "/" & d(0) & "/" & d(2)
end function

Resources