How do I create a rolling date filter in Power Query? - powerquery

Here is what I have:
Result = Table.SelectRows(
#"Filtered Rows",
each [LATEST_ACCEPTABLE_DATE]
<= Date.AddDays(
#date(DateTime.LocalNow(),17)
)
)
It returns:
Expression.Error: 2 arguments were passed to a function which expects 3.
I'm not sure where it expects a 3rd argument....

If you don't understand your code, consider formatting it properly:
Result = Table.SelectRows(
#"Filtered Rows",
each [LATEST_ACCEPTABLE_DATE]
<= Date.AddDays(
#date(DateTime.LocalNow(),17)
)
)
Now you can easily see that you are using the #date() constructor with just 2 parameters instead of 3:
#date(year as number, month as number, day as number) as date
Actually, you don't need it here. Use instead:
Date.From(DateTime.LocalNow())

Related

PowerBI: same IDs for consecutive data

I have a question about generating IDs in power BI.
Question: I have the table like following:
I'd like to generate same IDs for consecutive data (it means that end date of previous row equals to start date of current row), that has equal values in column 'Type', but IDs have to be different, if data is not consecutive. The example of correct IDs are below.
(Note that 'Bike' has different Ids because these rows are NOT consecutive)
Can you help me please with writing DAX command or Query? Every advice would be very helpful.
I created 3 separate calculated columns in order to accomplish this , with the final IDs column being the result you're looking for. I've included the DAX below, just replace the "Table1" references with your table's name. Skip down to the bottom to see an image of how the final table looks (Results Table).
First Calculated Column
Create a unique string ID for each row in the table. Specify "Same" for rows that will inherit the previous unique ID. This makes use of the EARLIER function and a solution similar to Get Value from Previous Row post on the Community page in order to evaluate the previous row in a calculation.
First Iteration IDs =
VAR previousRow =
TOPN(
1,
FILTER(
Table1,
Table1[Start Date] < EARLIER(Table1[Start Date])
&& Table1[Type] = EARLIER(Table1[Type])
),
[Start Date],
DESC
)
VAR previousEndDate = MINX(previousRow, [End Date])
VAR previousType = MINX(previousRow, [Type])
RETURN
IF(
Table1[Start Date] = previousEndDate && Table1[Type] = previousType,
"Same",
CONCATENATE(FORMAT(Table1[Start Date], "dd/mm/yyyy"), CONCATENATE(" ", Table1[Type]))
)
Second Calculated Column
Convert all of the "Same" IDs from the previous column to their respective IDs in that column.
Second Iteration IDs =
VAR previousRow =
TOPN(
1,
FILTER(
Table1,
Table1[Start Date] < EARLIER(Table1[Start Date])
&& Table1[Type] = EARLIER(Table1[Type])
&& NOT(Table1[First Iteration IDs] = "Same")
),
[First Iteration IDs],
DESC
)
VAR previousID = MINX(previousRow, [First Iteration IDs])
RETURN
IF(
Table1[First Iteration IDs] = "Same",
previousID,
Table1[First Iteration IDs]
)
Third Calculated Column
Use the RANKX function to create more user-friendly number IDs from the string IDs in the previous column. This is the original column that you had asked for.
IDs = RANKX(Table1, Table1[Second Iteration IDs], , 1, Dense) - 1
I've included a results table below based on the sample table that you provided. You may need to play around with the unique string ID format or the RANKX function depending on how your actual data looks.

Elegant way to make a SUm

I need a query (in Oracle), that will be inside a stored procedure, where I can get a sum of the Amount value of Table REV.
The YEAR and one MONTH will be received as a parameter in the stored procedure, as YY and MM.
What I want is to sum the amount values since the 1st month of the year UP to the MM passed in the argument.
So
if MM in the argument is 02, I want to take the sum of amounts of months 01 + 02
if MM in the argument is 05, I want to take the sum of amounts of months 01+02+03+04+05
So MM is the last month to be summed.
How can I make this in the most efficient and elegant way?
CREATE OR REPLACE PROCEDURE "GET_YTD_AMOUNT" (YY in VARCHAR,
MM in VARCHAR)
select
ACT.LABEL ,
R.YEAR,
R.MONTH,
sum(R.AMOUNT)
from
ACTIVITY ACT,
REV R
where
R.YEAR=YEAR and
R.MONTH ??
R.ID_CODE = ACT.ID_CODE
I'd prefer using numeric variables rather than strings for such cases.
In your case ;
considering your year and month parameters are of string type, you need a to_number() conversion with less than or equal to operator
to_number(R.MONTH) <= to_number(i_month)
add an out parameter o_amount to return the result you get
of course, you need to convert your SQL format containing explicit
joins
better to define parameters ( or local variables ) by their type
within the tables in which they're contained. Btw, I didn't define o_amount by rev.amount%type against probability of sum() aggregation might exceed the precision of numeric value provided it's defined as so within the table.
So,use :
CREATE OR REPLACE PROCEDURE GET_YTD_AMOUNT(
i_year in rev.year%type,
i_month in rev.month%type,
o_amount out number
) IS
BEGIN
select sum(r.amount)
into o_amount
from activity a
join rev r
on r.id_code = a.id_code
where r.year = i_year
and to_number(r.month) <= to_number(i_month);
END;
/
You can use less than equal to:
select
ACT.LABEL ,
R.YEAR,
Max(R.MONTH) || '-' || Max(R.MONTH) as months_from_to
sum(R.AMOUNT)
from
ACTIVITY ACT,
REV R
where
R.YEAR= YY and -- it should be YY
R.MONTH <= MM -- less than equal to with MM
R.ID_CODE = ACT.ID_CODE
Group by ACT.LABEL ,
R.YEAR
Note: You must re-design your DB to store dates in date data type.
Cheers!!

Specifying starting value in sorting/Sort starting from middle - Progress openedge

Scenario: I have a char field(name:priority) in my table where values are stored as 1,2,3 and blank("").
for each mytable no-lock by priority:
This query sorts in this order: blank,1,2,3.
for each mytable no-lock by priority desc:
And,this query sorts records like this: 3,2,1 and blank.
But i need to sort the records like this: 1,2,3 and then blank. In ascending order but skipping the blank and starting from 1.
Is there any way to sort this out in Progress?
Since you are using a character field, it's treating the numbers as strings. The ASCII values for the strings "1", "2" and "3" are 49, 50 and 51. Progress treats a blank ("") as ASCII -1. That's why the blank comes first.
Your best bet would be to use two FOR EACH statements. First do the non-blank records:
FOR EACH mytable NO-LOCK WHERE mytable.priority <> "" BY priority:
Then do the blank records:
FOR EACH mytable NO-LOCK WHERE mytable.priority = "":
If you have your business logic in procedures/functions, you can run those from within the FOR EACH loops to prevent any code duplication.
If (only if) theres not that many records in the table perhaps you can copy the records to a temp-table with a new priority and sort the temp-table instead?
If you have million of records this might not be it! Then I would consider simply adding a new field.
DEFINE TEMP-TABLE MyTable NO-UNDO
FIELD priority AS CHARACTER
FIELD txt AS CHARACTER.
CREATE MyTable.
ASSIGN MyTable.priority = "1"
MyTable.txt = "First?".
CREATE MyTable.
ASSIGN MyTable.priority = ""
MyTable.txt = "Last?".
DEFINE TEMP-TABLE ttMyTable NO-UNDO LIKE MyTable
FIELD newPriority AS INTEGER
INDEX sortOrder newPriority.
FOR EACH MyTable NO-LOCK:
CREATE ttMyTable.
BUFFER-COPY MyTable TO ttMyTable
ASSIGN
ttMyTable.newPriority = IF MyTable.priority = "" THEN 99999 ELSE INTEGER(MyTable.priority).
END.
FOR EACH ttMyTable NO-LOCK BY ttMyTable.newPriority:
DISPLAY ttMyTable.
END.
Since you are scanning /all/ records anyway, you could sort in the BY:
define temp-table tt no-undo
field priority as character
.
create tt. tt.priority = "".
create tt. tt.priority = "1".
create tt. tt.priority = "2".
create tt. tt.priority = "3".
create tt. tt.priority = "".
for each tt by ( if tt.priority = "" then "4" else tt.priority ):
display string( rowid( tt ) ) tt.priority.
end.

DAX - Lookup value to retrieve exchange rate

In table "Paypal", I have:
And in table "Câmbios":
And now, I'm adding a calculated column to "Paypal" table with the formula:
Câmbio = LOOKUPVALUE('Câmbios'[Câmbio];'Câmbios'[Mês];MONTH('Paypal'[Date]))
Which is returning the error:
A table of multiple values was supplied where a single value was expected.
This doesn't make sense to me.
Can anyone help?
Thanks
The problem is Câmbios table contains repeated values for at least one month and the LOOKUPVALUE function doesn't know which value use to retrieve the specified column.
You can use instead:
Cambio =
CALCULATE (
MAX ( Cambio[Cambio] ),
FILTER ( Cambio, [Mes] = MONTH ( EARLIER ( Paypal[Date] ) ) )
)
Or delete the repeated values from Cambios[Mes].

INDEX ON Date Range and a Uniqe Number VFP

I need to change a select statement in VFP to do a simple task (select all records in a date range and by a Employee Number). I have tried everything I can think of. I know I can do it in SQL select but I just want to use the table I have and not a cursor.
I'm trying something like this
INDEX ON Date >= ThisForm.DateFrom+Date + Date=< ThisForm.DateTo+ALLTRIM(empid) TAG MyOrder
I know how INDEX ON works but my format is wrong.
Maybe you meant a filtered index. However you don't need to do such a thing. You could simply have an index combining employee number (I suppose it is an integer) and the date. Then you can use a simple for and while scoping clauses or range or alike (you really didn't explain what you would do) - and even an SQL might be the easier way depending on what you would do.
ie: (using date as a column name is a bad idea, but that is another matter)
INDEX ON padl(empId, 10, '1') + dtoc(Date,1) TAG MyOrder
Having such an index you could scan all the records for a given employee in a date range like this:
local lnEmployee, lcStart, lcEnd
lnEmployee = 1 && whatever the employee number is
lcStart = padl(m.lnEmployee, 10, '1')+dtoc(ThisForm.DateFrom,1)
lcEnd = padl(m.lnEmployee, 10, '1')+dtoc(ThisForm.DateTo,1)
scan for padl(empId, 10, '1') + dtoc(Date,1) >= m.lcStart and ;
padl(empId, 10, '1') + dtoc(Date,1) <= m.lcEnd
* whatever
endscan
This would do the same:
local lnEmployee, lcStart, lcEnd
lnEmployee = 1 && whatever the employee number is
lcStart = padl(m.lnEmployee, 10, '1')+dtoc(ThisForm.DateFrom,1)
lcEnd = padl(m.lnEmployee, 10, '1')+dtoc(ThisForm.DateTo,1)
set order to tag myOrder
set range to m.lcStart, m.lcEnd
scan
* whatever
endscan
PS: Actually with indexes on empid and date, a simple scan for ... would do too. ie:
scan for empId = m.lnEmpoyee and ;
Date >= ThisForm.DateFrom and ;
Date <= ThisForm.DateTo
*...
endscan
Welp don't really like filter but if any one has a better idea let me know!
Set Filter To Date >= ThisForm.DateFrom .And. Date =< ThisForm.DateTo .And. EmpID = AllTrim(ThisForm.Combo1.Value)

Resources