How to find the minimum value for 1-many relationship? - openedge

I want to find the minimum date value in a list of transactions that are associated with an investment. There are many transactions for one investment, clearly. How do I write this so that Progress will only give me the minimum transaction date? I get the minimum at the end of my list, but I do not want the list, just the minimum value.
FOR EACH ilinvest WHERE ilinvest.inv-num EQ 406885:
FOR EACH iltrans WHERE iltrans.reg-pin EQ ilinvest.reg-pin:
DISPLAY iltrans.tran-dt(MINIMUM).
END.
END.

If you have an index on the tran-dt field, you could do something like
FOR EACH ilinvest WHERE ilinvest.inv-num EQ 406885:
FOR EACH iltrans WHERE iltrans.reg-pin EQ ilinvest.reg-pin
BY iltrans.tran-dt ASCENDING:
// The iltrans.tran-dt value here is the lowest. Note that
// you may see the unknown value .
// Leave after getting the first record
LEAVE.
END.
END.

Thank you both for your help. Removing the ascending worked like a charm:
FOR EACH ilinvest:
FOR EACH iltrans WHERE iltrans.reg-pin EQ ilinvest.reg-pin
AND iltrans.acct-num EQ ilinvest.inv-num
BY iltrans.tran-dt:
iMin = iltrans.tran-dt.
LEAVE.
END.
END.

Beware if your date field has no value, ie the unknown value (?). If the unknown value sorts before or after other values depends on all sorts of black magic
Additionally, since I do not like leave, I prefer a while:
def var dt min as date no-undo.
for each ilinvest no-lock,
each iltrans
where iltrans.reg-pin = ilinvest.reg-pin
and iltrans.acct-num = ilinvest.inv-num
no-lock
by iltrans.tran-dt
while dtmin = ?:
if iltrans.trans-dt <> ? then
dtmin = iltrans.tran-dt.
end.

Related

Adding more "AND" conditions to FOR LAST causing performance issue

I'm new to progress 4GL. I'm trying to find last record from a table. But its causing performance issue. I directly copied my query here so it should be syntax error. Please help me to modify the logic or give me suggestion.
Note - Syntax(USE-SYNTAX) available only for following fields but not sure adding this to for last is good idea.
pc_domain,
pc_list_classification,
pc_list,
pc_curr,
pc_prod_line,
pc_part,
pc_um,
pc_start
for last pc_mstr no-lock
where pc_domain = global_domain
and pc_list_classification = 1
and pc_curr <> ""
and pc_part = b_ps_mstr.ps_comp
and pc_um <> ""
and (pc_start <= v_end[v_i]
or pc_start = ?)
and (pc_expire >= v_end[v_i]
or pc_expire = ?)
and (pc_amt_type = "L"
or pc_amt_type = "P"):
end.
if not available pc_mstr then
do:
for last pc_mstr no-lock
where pc_domain = global_domain
and pc_list_classification = 1
and pc_curr <> ""
and pc_part = b_ps_mstr.ps_comp
and pc_um <> ""
and (pc_amt_type = "L"
or pc_amt_type = "P"):
end.
end.
What do you mean with last? Do you mean LAST as in what Progress means:
LAST Uses the criteria in the record-phrase to find the last record in the table that meets that criteria. The AVM finds the last record before sorting.
Or do you mean something else? Like the last record created? Depending on what you mean you might have to do different things.
Some pointers about performance though:
Basically where clauses using = is good, >, <, >=, <=, BEGINS etc is decent and <>, NOT is BAD.
But it also boils down to what index you can use. You need to know about the indices of the table! But regardless of indices: those <> will make you unhappy. They will cause "table scans" (the entire table will be read).
<> "" could perhaps be replaced with > "" in this case - a little less evil.
Also you need to use () in a better way with those or's. Otherwise you might not get what you want. OR will win over AND so A AND B OR C really is run as (A AND B) OR C. Maybe you really ment A AND (B OR C) - in that case you need to use those ( ) wisely.

Power BI DAX: Subtracting one hour from SELECTEDVALUE datetime

I am using the following measure (and a calendar table) to determine equipment uptime for a given hour of the day based on user input from a datetime slicer:
Selected Hour =
CALCULATE (
'UptimeView'[Uptime %],
FILTER (
'UptimeView',
'UptimeView'[LocalShiftDateHour] = SELECTEDVALUE ( 'CalendarTable'[DateTime] )
)
)
This is working just fine. The problem is that I also need this same calculation performed for each of the 12 hours prior to the selected hour. When I try to use the same formula but with one hour subtracted from the SELECTEDVALUE, like so...
S-1 =
CALCULATE (
'UptimeView'[Uptime %],
FILTER (
'UptimeView',
'UptimeView'[LocalShiftDateHour]
= SELECTEDVALUE ( 'CalendarTable'[DateTime] ) - ( 1 / 24 )
)
)
... I get blank cells in my table visualization, even though I know there is data for that hour:
Why does this happen? Any time I try to perform mathematical operations on the SELECTEDVALUE datetime value, it gives me blanks. But without using operations to manipulate it and just using the selected datetime itself, it works no problem. Is it not possible to subtract an hour from a SELECTEDVALUE datetime? If not, what workaround(s) should I try? (I have also attempted using -TIME(1,0,0) instead of -1/24 but that gave me blanks as well.)
Thanks in advance!!
I think the reason is that the subtraction you are operating isn't convenient to go row by row. Would you please try rather to put it as follows, and put the MAXX() function around the calculus you did, while adding another argument, which is the name of the table in which you want the subtraction to be performed:
S-1 =
CALCULATE (
'UptimeView'[Uptime %],
FILTER (
'UptimeView',
'UptimeView'[LocalShiftDateHour]
= MAXX('Replace_with_Tablename',SELECTEDVALUE(
'CalendarTable'[DateTime] ) - ( 1 / 24 ))
)
)
This is the trick I use. In fact, MAXX(tablename, expression) Evaluates an expression for each row of a table and returns the largest value.
Don't worry about the max, it doesn't have any effect on the result, since the max(one precise value in a precise row)= that same value

Does a OUTER-JOIN always divide the query in two parts, leaving the part on the right empty if not complete in Progress?

I'm trying to do an OUTER-JOIN in progress using this page as inspiration. My code is as follows
OPEN QUERY qMovto
FOR EACH movto-estoq
WHERE movto-estoq.lote BEGINS pc-lote
AND movto-estoq.it-codigo BEGINS pc-it-codigo
AND movto-estoq.dt-trans >= pd-data1
AND movto-estoq.dt-trans <= pd-data2
AND movto-estoq.cod-emitente = pi-cod-emitente,
EACH item OUTER-JOIN
WHERE movto-estoq.it-codigo = item.it-codigo,
EACH item-cli OUTER-JOIN
WHERE item-cli.item-do-cli BEGINS pc-item-cli
AND movto-estoq.cod-emitente = item-cli.cod-emitente
AND movto-estoq.it-codigo = item-cli.it-codigo
AND movto-estoq.un = item-cli.unid-med-cli,
EACH nota-fiscal OUTER-JOIN
WHERE movto-estoq.nro-docto = nota-fiscal.nr-nota-fis
BY movto-estoq.dt-trans DESCENDING BY movto-estoq.hr-trans DESCENDING.
The problem that is happening is when 1 element in null, all the other elements that are in the OUTER-JOIN are appearing as null as well, even though they are not null. Is there a better way to write this code? Should I put 'LEFT' before the OUTER-JOIN? Thanks for your time.
To make your example easier, consider making it work from ABL dojo. The following code:
define temp-table ttone
field ii as int
.
define temp-table tttwo
field ii as int
field cc as char
.
create ttone. ttone.ii = 1.
create ttone. ttone.ii = 2.
create tttwo. tttwo.ii = 2. tttwo.cc = "inner".
create tttwo. tttwo.ii = 3. tttwo.cc = "orphan".
define query q for ttone, tttwo.
open query q
for each ttone,
each tttwo outer-join where tttwo.ii = ttone.ii.
get first q.
do while available ttone:
message ttone.ii tttwo.cc.
get next q.
end.
Can be run from https://abldojo.services.progress.com/?shareId=600f40919585066c219797ed
As you can see, this results in :
1 ?
2 inner
The join which is not available is shown as unknown. The value of the outer part of the join is shown.
Since you do not show how you are getting an unknown value for everything, maybe you are concatenating the unknown values?

javascript for Array how many and min

I am trying to create a form in Acrobat. I want it to do some calculations. I got almost all of them done aside from 2.
I have an array of cells DF1 to DF78 so I need a calculation script that will give me the minimum value in that array not counting the blank ones.
In the same array of cells DF1 to DF78 I need a calculation script to find how many fields in that array have value and bring me up the number.
I already tried using the min option on the acrobat DC and selecting the fields. Ii want to look at DF1 to DF78. However, it always shows 0 because it's counting the empty fields as well.
I tried looking online, but all the scripts that they show are very confusing. I can't find where to put the array in there.
I wish I had a script to put it in here... sorry.
I have fields DF1 to DF78 so a total of 78 fields, and I need to find the minimum value in that array not including the fields that are blank.
Another script for the same fields DF1 to DF78 needs to count how many of the fields actually have data ex: DF1, DF2, DF3 had data on it and the rest are empty so it should display the number 3 because 3 of the 78 fields have data in them.
I hope somebody can help me with this.
This should work... Add it to the calculate action of a new hidden field you want the numbers to show up. Fix the names on the last two lines first.
valueArray = [];
for (var i = 1; i <= 78 ; i++) {
//Get the fieldvalue by assembling the name with the prefix and the number increment
var fieldVal = this.getField("DF"+i).value;
//Acrobat field values are never null. The value of a blank field is an empty string
if (fieldVal != "") {
//Add non-empty field values to an Array.
valueArray.push(fieldValue);
}
}
// Get the minimum value in the array.
var minValue = Math.min.apply(null, valueArray);
// Get the number of non-blank fields.
var nonBlankFields = valueArray.length;
this.getField("RESULT FOR YOUR 1st QUESTION FIELD NAME HERE").value = minValue;
this.getField("RESULT FOR YOUR 2nd QUESTION FIELD NAME HERE").value = nonBlankFields;

Only incremental values - PowerBI Calculate between dates

this might look simple.. but dk how to do it
this is the information:
So.. i got the Cumulative Total using this function:
CumulativeTotal = CALCULATE(
SUM(vnxcritical[Used Space GB]),
FILTER(ALL(Datesonly[Date]),
Datesonly[Date] <= MAX(Datesonly[Date])))
But what i need is to get the differences between the dates, in the first date and the second the difference will be of 210. I need to get another column with that information. know the formula to do that?
ok..
So.. i used this:
IncrmentalValueTEST =
VAR CurrDate = MAX(vnxcritical[Date])
VAR PrevDate = CALCULATE(LASTDATE(vnxcritical[Date]), vnxcritical[Date] < CurrDate)
RETURN SUM(vnxcritical[Used Space GB]) -
CALCULATE(SUM(vnxcritical[Used Space GB]), vnxcritical[Date] = PrevDate)
and this is the result:
Ok, so this is is my data table:
You can see all the dates that i have for now, this is a capacity report for diferents EMC Storage Arrays, for diferentes Pools. The idea would be to have the knolwdge to review the incremental space used in a determinated portion of time.
allready tried another idea to get this, but the result was the same.. i used this:
Diferencia =
Var Day = MAX(Datesonly[Month])
Var Month = MAX(Datesonly[Year])
RETURN
SUM('Used Space'[used_mb])
- CALCULATE(
SUM('Used Space'[used_mb])
,FILTER(ALL(Datesonly[Date]),Datesonly[Date] <= Max(Datesonly[Date])))
But the return is the same.. "47753152401"
i'm using graphical filters, and other things to get a minimal view, because there are only 5 weekly reports and the sql database got more than 150.000 rows.
and this is the relation that i made with a only a table full of "dates" in order to invoke the function in a better way, but the result is the same..
Try something along these lines:
IncrmentalValue =
VAR CurrDate = MAX(Datesonly[Date])
VAR PrevDate = CALCULATE(LASTDATE(Datesonly[Date]), Datesonly[Date] < CurrDate)
RETURN SUM(vnxcritical[Used Space GB]) -
CALCULATE(SUM(vnxcritical[Used Space GB]), Datesonly[Date] = PrevDate)
First, calculate the current date and then find the previous date by taking the last date that occurred before it. Then take the difference between the current value and the previous value.

Resources