How do you repeat rows in a table multiple time - dax

I created a table a DAX Studio and want to repeat all the rows (with all the columns) in a new table multiple times; to my choosing.
//create temp table of Historic Facilities for all annual groups 1 to 3
TABLE HistFac =
ADDCOLUMNS ( FacSchHist,
"Rank", RANKX ( FacSchHist, [WtAvg] ),
"Annual Group", (RANKX ( FacSchHist, [WtAvg] ) - FLOOR((RANKX ( FacSchHist, [WtAvg] ) - 1) /3 * 3,3)))
EVALUATE
NonHistFac
ORDER BY [Annual Group],
[WtAvg] DESC
I want the maintain the original order in the repeated list. There are obviously many ways to construct a table (see code above); however, how does one repeat the list of rows?
Thanks you for any suggestions.

Try to remove the filters that are affecting the measure inside RANKX because of the context transition coming from the table provide in the first argument of GENERATE
DEFINE
TABLE HistFac =
GENERATE (
{ 1, 2, 3 },
ADDCOLUMNS (
ADDCOLUMNS (
FacSchHist,
"#Rank",
RANKX (
FacSchHist,
CALCULATE ( [WtAvg], REMOVEFILTERS ( TableSupliedInTheFirstArgument ) )
)
),
"Annual Group",
[#Rank]
- FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
)
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC
Or simply use variables to compute in a different filter context.
DEFINE
TABLE HistFac =
VAR RankedTable =
ADDCOLUMNS ( FacSchHist, "#Rank", RANKX ( FacSchHist, [WtAvg] ) )
VAR SomeCalculationOnRankedTable =
ADDCOLUMNS (
RankedTable,
"Annual Group",
[#Rank]
- FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
RETURN
GENERATE ( { 1, 2, 3 }, SomeCalculationOnRankedTable )
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC

You can use GENERATE for repeating the rows:
DEFINE
TABLE HistFac =
GENERATE (
{ 1, 2, 3 },
ADDCOLUMNS (
FacSchHist,
"Rank", RANKX ( FacSchHist, [WtAvg] ),
"Annual Group",
(
RANKX ( FacSchHist, [WtAvg] )
- FLOOR ( ( RANKX ( FacSchHist, [WtAvg] ) - 1 ) / 3 * 3, 3 )
)
)
)
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC
A better way to write this code will be to use nested ADDCOLUMNS:
DEFINE
TABLE HistFac =
GENERATE (
{ 1, 2, 3 },
ADDCOLUMNS (
ADDCOLUMNS ( FacSchHist, "#Rank", RANKX ( FacSchHist, [WtAvg] ) ),
"Annual Group",
[#Rank]
- FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
)
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC

AntrikshSharma - I will give those a try now , appreciate your guidance.
Okay, the code worked fine; but uncovered a problem. After the initial ranking of the list, and before the replication - I do not want to continue ranking.
In other words, I want the initial ranked-list to be reproduced 3x without any further ranking; just have each duplicated occurrence appear after the initial list in the exact order.
If the initial list was 12345, then 12345,12345,12345 - thank you for the more efficient code as well.

AntrikshSharma, your comment and code, "Or simply use variables to compute in a different filter context" is genius. The code performed as expected. The problem I'm experiencing is with the UNION of the two tables "NonHistFac" and "HistFac". I will provide an image to explain then the most current code.
15yr cycle of Hist & NonHist Facilities
The image shows the goal. combine the NonHistFac (all surveyed every 5yrs) with the HistFac (all surveyed every 3yrs). The original ranking must be maintained (this is currently met.)
Here is the problem. The numbers within the image are the Values as produced by the GENERATE function. When the tables are combined and the NonHistFac are mixed with the HistFac, they are not evenly distributed throughout the 1 to 5 Values.
What appears in Values 4 and 5 is obviously the remaining HistFac. I need to have the entire combination distributed from 1 to 5; or as shown, over the 15 year cycle.
Thank you.
// produce non-historic table with additional columns and replicate all rows 3x
TABLE NonHistFac =
VAR NonHistRankedTable =
ADDCOLUMNS ( FacSchNonHist, "#Rank", RANKX ( FacSchNonHist, [WtAvg] ) )
VAR NonHistAnnualizedRankedTable =
ADDCOLUMNS (
NonHistRankedTable,
"Annual Group",
[#Rank] - FLOOR ( ( [#Rank] - 1 ) / 5 * 5, 5 )
)
RETURN
GENERATE ( { 1, 2, 3 }, NonHistAnnualizedRankedTable )
// from the FLOOR & GENERATE functions, 5 x 3 = 15 (this is a 15 year cycle)
//produce historic facility table with additional columns and replicate all rows 5x
TABLE HistFac =
VAR HistRankedTable =
ADDCOLUMNS ( FacSchHist, "#Rank", RANKX ( FacSchHist, [WtAvg] ) )
VAR HistAnnualizedRankedTable =
ADDCOLUMNS (
HistRankedTable,
"Annual Group",
[#Rank] - FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
RETURN
GENERATE ( { 1, 2, 3, 4, 5 }, HistAnnualizedRankedTable )
// from the FLOOR & GENERATE functions, 3 x 5 = 15 (this is a 15 year cycle)
// combine the tables NonHistFac & HistFac to create one-table representing a 15 yr cycle
VAR FacSchUnion =
UNION(
NonHistFac,
HistFac
)
VAR FacSch15yr =
DISTINCT(FacSchUnion)
EVALUATE
FacSch15yr
ORDER BY [Value],
[Annual Group],
[WtAvg] DESC

Related

Oracle sql query to convert common rows to columns

I had a requirement to build a survey like application. Did this using Oracle APEX 18.2. I'm done designing the table structures and their relationships. I'm now on the part where I need to build a report (can be Interactive Report/Classic Report) where the columns will depend on what questions are available.
So basically, each question is supposed to have a column in the report. I can build the report and add these questions as column on design time. But I was wondering if there is a way to do this at runtime as well? More questions can be added in the future and I would like to report to be flexible enough to accommodate this. For now I would like to try via SQL statement.
Here's my table design for refence.
create table persons (
id number primary key
, name varchar2(100) not null
)
/
insert into persons values ( 1, 'Bruce' )
/
insert into persons values ( 2, 'Jennifer' )
/
create table questions (
id number primary key
, question varchar2(100) not null
)
/
insert into questions values ( 1, 'Gender' )
/
insert into questions values ( 2, 'Currently Employed' )
/
create table choices (
id number primary key
, choice varchar2(100) not null
)
/
insert into choices values ( 1, 'Male' )
/
insert into choices values ( 2, 'Female' )
/
insert into choices values ( 3, 'Yes' )
/
insert into choices values ( 4, 'No' )
/
create table question_choices (
id number primary key
, question_id number
, choice_id number
)
/
insert into question_choices values ( 1, 1, 1 )
/
insert into question_choices values ( 2, 1, 2 )
/
insert into question_choices values ( 3, 2, 3 )
/
insert into question_choices values ( 4, 2, 4 )
/
create table survey (
id number primary key
, name varchar2(100) not null
)
/
insert into survey values ( 1, 'Survey 1' )
/
create table survey_questions (
id number primary key
, survey_id number
, question_id number
)
/
insert into survey_questions values ( 1, 1, 1 )
/
insert into survey_questions values ( 2, 1, 2 )
/
create table survey_responses (
id number primary key
, survey_id number
, person_id number
, question_id number
, choice_id number
)
/
insert into survey_responses values ( 1, 1, 1, 1, 1 )
/
insert into survey_responses values ( 2, 1, 1, 2, 4 )
/
insert into survey_responses values ( 3, 1, 2, 1, 2 )
/
insert into survey_responses values ( 4, 1, 2, 2, 3 )
/
commit
/
I did a bit or research and found out about the pivot command. However, this approach also requires that the columns be defined at design time.
select *
from (
select s.name survey
, p.name respondent
, q.question
, c.choice
, row_number() over (partition by person_id, question order by choice ) rn
from persons p
, questions q
, choices c
, question_choices qc
, survey s
, survey_questions sq
, survey_responses sr
where p.id = sr.person_id
and q.id = sr.question_id
and c.id = qc.choice_id
and s.id = sq.survey_id
and sq.question_id = q.id
and sr.choice_id = c.id
)
pivot (max(question) question, max(choice) for question in ( 'Gender','Currently Employed' ))
Appreciate any comments/suggestions.

DAX/PowerBI Rank taking a variable/parameter into account

I'm working on a ranking/scoring system and I'm missing the PERCENTRANK.INC function in powerBI. Instead I have worked out below formula which is the closest I can get.
Score =
DIVIDE (
RANKX (
FILTER ( 'Table', NOT ( ISBLANK ( [Sold amounts] ) ) ),
[Sold amounts],
,
ASC
) - 1,
COUNTROWS ( FILTER ( 'Table', NOT ( ISBLANK ( [Sold amounts] ) ) ) ) - 1
)
I really want to have the formula to take the type of "Fruit" into account in my scoring/ranking.
In short each fruit should be scored separately, with a range per fruit sold.
Could this somehow be done with a variable (VAR)?
Example of data:
This should work.
Score =
VAR fruit = 'Table'[Fruit]
VAR filteredTable = FILTER ( 'Table', NOT ( ISBLANK ( [Sold amount] ) ) && 'Table'[Fruit] = fruit)
RETURN
DIVIDE (
RANKX (
filteredTable,
[Sold amount],
,
ASC
) - 1,
COUNTROWS ( filteredTable ) - 1
)

how to compute the growth rate in Power Bi using Dax?

I want to have a column in power bi showing the growth rate of sales. I have a table like
year
count
1395
123
1396
232
1397
23
1398
908
1399
678
1400
34
the growth rate is (this year - previous year)/previous year
could you please guide me how I can do this?
When I use the growth the data is like below
You can add a calculated column like this:
growth =
VAR _currentcount = 'Table'[count]
VAR _currentyear = 'Table'[year]
VAR _previouscount =
CALCULATE (
SELECTEDVALUE ( 'Table'[count] ) ,
ALL ( 'Table' ) ,
'Table'[year] = _currentyear - 1
)
RETURN
IF (
NOT ISBLANK ( _previouscount ) ,
DIVIDE ( _currentcount , _previouscount ) - 1
)
or a measure like this, to be used with your year dimension:
growth_measure =
VAR _currentcount = SELECTEDVALUE ( 'Table'[count] )
VAR _currentyear = SELECTEDVALUE ( 'Table'[year] )
VAR _previouscount =
CALCULATE (
SELECTEDVALUE ( 'Table'[count] ) ,
ALL ( 'Table' ) ,
'Table'[year] = _currentyear - 1
)
RETURN
IF (
NOT ISBLANK ( _previouscount ) ,
DIVIDE ( _currentcount , _previouscount ) - 1
)
Giving this result:
All depending on your needs.

How to distinctly count customer IDs that visited a store in a given quarter only if the same customer ID visited in the previous quarter

I have a table
+-----------+----------+--------+-------+---------+
|Customer ID|Visit Date|Category|Product|Served by|
+-----------+----------+--------+-------+---------+
|1001 |03/17/2019|A |P11 |Jone Doe |
|1003 |03/17/2019|D |P12 |Jone Doe |
|1006 |03/15/2019|C |P13 |Jone Doe |
|1009 |03/10/2019|G |P14 |Jone Doe |
|1011 |12/12/2018|H |P15 |Foo Bar |
|1003 |11/11/2018|D |P16 |Foo Bar |
|1006 |09/10/2018|C |P17 |Foo Bar |
|1009 |10/10/2018|G |P18 |Foo Bar |
+-----------+----------+--------+-------+---------+
there are 4 customers but only 2 (1003 and 1009) visited in the previous quarter.
I used DATESINPERIOD but it counts all distinctly between the preceding quarters (I have a designated date table).
1st approach
customers_count =
CALCULATE (
DISTINCTCOUNT[Customer ID],
DATESINPERIOD (
'Calendar'[Date],
ENDOFQUARTER ( 'Calendar'[Date] ),
-2,
QUARTER
)
)
2nd approach
customers_count 2Q =
VAR customers_count_1 =
DISTINCT ( FILTER ( VALUES ( Orders[Customer ID] ) ) )
VAR customers_count_2 =
CALCULATETABLE (
DISTINCT ( FILTER ( VALUES ( Orders[Customer ID] ) ) ),
DATEADD ( 'Calendar'[Date], -1, QUARTER )
)
RETURN
COUNTROWS ( INTERSECT ( customers_count_1, customers_count_2 ) )
The expected count is 2 for the last quarter.
Your second approach looks reasonable. Try it without DISTINCT and FILTER.
customers_count 2Q =
VAR customers_count_1 =
VALUES ( Orders[Customer ID] )
VAR customers_count_2 =
CALCULATETABLE (
VALUES ( Orders[Customer ID] ),
DATEADD ( 'Calendar'[Date], -1, QUARTER )
)
RETURN
COUNTROWS ( INTERSECT ( customers_count_1, customers_count_2 ) )
The VALUES function returns a list of distinct values of its column argument that are within its filter context.

How to pass a filtered table to RankX

I would like RankX to rank products for Var2 and only consider/see products who have a value for Var1 (so only A and B and not C).
Here is an example datamodel including the resulting pivottable
And here are the measures I use:
SUM Value = SUM ( Data[Value] )
Var1 Check = CALCULATE ( COUNTROWS ( Data ), Variable[Variable] = "Var1" )
RankX = RANKX ( ALL ( 'Product' ), [SUM Value] )
RankX Filter = IF ( ISBLANK ( [Var1 Check] ), BLANK (), [RankX] )
The idea is that my filtered RankX function (RankX Filter) shows 2 instead of 3 for Product B as only A and B should be considered.
Using DAX Studio I managed to filter my product table accordingly but I don't know whether this the right approach nor how to pass that filtered table to a RankX function.
FILTER (
ADDCOLUMNS (
'Product',
"Var1Check", CALCULATE ( COUNTROWS ( Data ), Variable[Variable] = "Var1" )
),
[Var1Check] = 1
)
You should just be able to put the filtered table as the first argument in your RANKX function. Something along these lines:
RANKX ( FILTER ( 'Product', Variable[Variable] = "Var1" ), [SUM Value] )

Resources