Power BI topn function: Problem with topn function returning more than n rows due to duplicates - duplicates

This is the current data table that I have, which is called 'Potential High Usage'
CLICK TO SEE DATA TABLE
I tried to use the TOPN function to create a table of the top 10 'User ID' based on the 'Number of clicks'. This is how I tried to do it:
High Usage IDs = topn(10,'Potential High Usage',[Number of clicks])
The problem is that it returns 11 rows instead of 10. I am thinking that its because I have many duplicates for the least number of clicks that will still be considered as top 10 (Number of clicks = 2). I was wondering if there is a way to return ONLY 10 rows?

Yes. TOPN will return more than N rows when there are ties at Nth row.
See the Microsoft TOPN dax function documentation.

First add index column using power query.
Then use following DAX to return top 10 rows.

Related

Select last row from a MySQL query

I have a query that returns some dates which are not in any order. I need to select the last row from the sub query. The problem is all the solutions I can find online uses something like
ORDER BY qry_doc_dates.arrival_date DESC LIMIT 1
Select qry_doc_dates.arrival_date
FROM (qry_doc_date) AS qry_doc_dates
ORDER BY qry_doc_dates.arrival_date DESC
LIMIT 1
which will not serve my purpose because it first orders the dates as DESC(or ASC).
Suppose the qry_doc_date returns :
"2019-05-27",
"2019-05-13",
"2019-05-20",
"2019-05-22",
"2019-07-12",
"2019-05-22",
"2019-07-16",
"2019-05-22"
As we can see that the returned values are not in order. If I use
ORDER BY qry_doc_dates.arrival_date DESC LIMIT 1
then it returns "2019-07-16" But I need "2019-05-22" which is the last row.
EDIT 1:
I am trying to convert this VBA query to MYSQL.
DLast("arrival_date", "qry_doc_date", "[package_id] = " & Me!lstPackage)
I suppose I misunderstood what the VBA query wants to return. Another issue is I do not have means to run this VBA query and check the result myself.
Your question doesn't make too much sense according to the SQL standard. In the absense of an ORDER BY clause the database engine is free to return the rows in any order. This order may even change over time.
So essentially you are requesting the "last random row" the query returns. If this is the case, why don't you get the "first random row"? It doesn't make any difference, does it?
The only way of getting the last random row is to get them all and discard all of them except for the last one.
Now, if you just need one random row, I would suggest you just get the first random row, and problem solved.
In response to the additional information from your edit:
EDIT 1: I am trying to convert this VBA query to MYSQL.
DLast("arrival_date", "qry_doc_date", "[package_id] = " & Me!lstPackage)
I suppose I misunderstood what the VBA query wants to return. Another
issue is I do not have means to run this VBA query and check the
result myself.
Unless your dataset qry_doc_date is ordered by means of an order by clause, the DFirst or DLast domain aggregate functions will return essentially a random record.
This is stated in the MS Access Documentation for these two functions:
You can use the DFirst and DLast functions to return a random record from a particular field in a table or query when you simply need any value from that field.
[ ... ]
If you want to return the first or last record in a set of records (a domain), you should create a query sorted as either ascending or descending and set the TopValues property to 1. For more information, see the TopValues property topic. From a Visual Basic for Applications (VBA) module, you can also create an ADO Recordset object and use the MoveFirst or MoveLast method to return the first or last record in a set of records.
What you need is to in qry_doc_date to include a sequential row number.
Then you can use something like this:
ORDER BY qry_doc_dates.row_number DESC LIMIT 1

Grouping a counted variable

I am quite new to SSRS and have what I imagine is a pretty simple question. I have the set up pictured below.
What I'm looking for is a list of dates that data exists for then a nested list of outcomes and then how many of each of those outcomes there were on that date. What I get is this,
I want 6/10/2016 > ABORT > to be 3 instead of 1 1 1. What am I doing wrong? Is it possible that I need to change my query somehow?
Try using:
=COUNT(Fields!sys_OUTCOME.Value,"sys_OUTCOME")
If you don't want to see details rows delete the Details group in the Row Groups pane.
Code Explanation:
COUNT: Returns a count of non-null values specified by the expression,
evaluated in the context of the given scope.
REFERENCE
Every aggregation function can summarize data in a given context of the given scope. In this case the scope I passed to the COUNT function is "sys_OUTCOME" group name (Row Groups) so it will return the count of sys_OUTCOME values by sys_OUTCOME group. If you don't specify the group scope it will count every row without grouping what you was getting initially.
Let me know if this helps.

How to Sum the aggregates of a child group

This should be easy, but I am stuck.
I have a table listing some figures about Qualifications - to achieve which a dataset that is essentially a row per Student is being grouped on Qualification with a Parent Grouping on "Measure" (which is just a bucket of qualifications).
One of the columns is trying to work out the number of students (well, more properly the number of students with a value in a particular field, weighted by another field) in each Measure/Qualification. In the screenshot below, it's the "Pred. Avg" column on the right hand side.
So for the Qualification Row Grouping, that column is calculated by:
=CountDistinct(Iif(IsNothing(Fields!AVG_PTS.Value) = False, Fields!Learner_ID.Value, Nothing), "Qual") * Lookup(Fields!Qual_Code.Value, Fields!Qual_Code.Value, Fields!size.Value, "DS_KS5Nationals_LKP")
This works fine - the values of 35 and 11.5 in that rightmost column are correct for those rows. What the top row should be doing is simply adding up the values in the other rows to give me the number of students in this Measure, in this case to give 46.5. To do that the expression I am using is:
=Sum(CountDistinct(Iif(IsNothing(Fields!AVG_PTS.Value) = False, Fields!Learner_ID.Value, Nothing), "Qual") * Lookup(Fields!Qual_Code.Value, Fields!Qual_Code.Value, Fields!size.Value, "DS_KS5Nationals_LKP"), "Measure")
However as you can see in the screenshot, this returns 2917 instead.
So my question is; Why doesn't that work, and given that it doesn't work how can I, within a parent group, aggregate the results of aggregates inside a child group?
EDIT:
OK so, I have determined that the following works correctly:
=Sum(CountDistinct(Iif(IsNothing(Fields!AVG_PTS.Value) = False, Fields!Learner_ID.Value, Nothing), "Qual"), "Measure")
The problem there is that the Qual row that returns 11.5 is weighted to 0.5. I.E. it actually returns 23, and the Lookup(Fields!Qual_Code.Value, Fields!Qual_Code.Value, Fields!size.Value, "DS_KS5Nationals_LKP") is for that row returning 0.5 and altering it to 11.5...so the question becomes; "how do I force that ...*Lookup(Fields!Qual_Code.Value, Fields!Qual_Code.Value, Fields!size.Value, "DS_KS5Nationals_LKP") into the "Qual" scope, like the CountDistinct() is already in?
The issue here is that you're trying to aggregate values using that Lookup function which only returns one value. There are a couple ways you could go about doing this. One option would be to use the LookupSet function to get the applicable weightings. An even better option is to combine the data in your dataset so that the weighting is available without using a lookup. That way the function can recalculate an any grouping level without you having to force a scope on it. Also, CountDistinct ignores "Nothing" so you can do without the extra IIf statement. Hope that helps.

grab mysql result based on field values

I am taking over designing a CMS from another programmer. As the site is filling up, we're finding loops in mysql queries causing long hangs. I have found a temp solution for this one, but am wondering if there is a quicker way of doing it?
take the table (tracks resources):
id resource click
1 res_1 192
2 res_2 12
3 res_3 300
what we need to get is a popularity of the resource - res_click/total_click
what he had was a while loop:
while ($item = mysql_fetch_array ($result)) $total_clicks = $total_clicks + $item[0];
As there could be 100 or more resources to a page, this was running for each resource, and it is causing major hangs.
My solution is to get a sum:
SELECT SUM(click) FROM uri
SELECT click FROM resource WHERE id=$x
then divide them both.
But this two calls are still running for around a 100 items per page. Is there a way I can have a field in mysql that is the result of a formula based on another another, like in excell? So I could add a field "percentage", tell mysql that it is the sum of click divided by the current click value, then every time click is updated the 'percentage' field is automatically updated?
any help would be appreciated,
cheers ;)
you can create a view on your table that present the sum you want

SSRS Row Group + Column Group = RowNumber Issue

I'm back with another SSRS question :-)
I'm dealing with survey data. I have a procedure that's returning an organization's response counts per question. So my report is defined as Group on Organization for row and Group on answer for columns. Both the number of organizations and answers are variable. That's working as expected. I've tried adding a RowCount next to the organization so that I can show rank, but the fact that each org has one row per question means that I'm getting eight rows per org.
Here's an example:
Here is my report definition:
The rank expression is currently: =RowNumber(Nothing)
Ideally, the rank would be 1, 2, 3, 4, etc... I've tried scope to the row group, column group and nothing. No help.
Any assistance would be greatly appreciated!
Had same frustrating issue; lots of time wasted. Eventually, this solution also helped:
=RunningValue(CountDistinct("YourTableName"),Count,"YourTableName")
Trick here is NOT to use the name of the group within the table/matrix, but the name of the table itself. And yes, one would think that using the table name for the scope in the function RowNumber should work, but it doesn't.
Try using:
runningvalue(Fields!AnswerText.Value,CountDistinct,"NameOfOrganizationGroup")
If its a matrix, change the name of the scope from the row scope to the matrix scope.
I do with custom code.
Add this to code section on report config:
Dim private count as integer = 0
Dim private iniRow as integer = 0
Public function nroFila(Byval rowNum as integer) as integer
if iniRow = 0 then
iniRow = rowNum
end if
if rowNum = iniRow then
count = 0
end if
count = count + 1
Return count
End function
Then, call the function in a cell inside the group:
=Code.nroFila(RowNumber(Nothing))
I seem to have found a solution, but it feels like a hack... I'm leaving this unanswered to see if someone else can provide a better solution (read less hackish).
My Rank Expression is now:
=RowNumber(Nothing)/Count(Fields!AnswerText.Value)
Everything seems to be ok. I suppose I should IIf(Count... = 0, Then RowNumber, else what I've got...
Best thing to do here, is make the Rank column equal to =RowCount()/8
Since your sure each visible row contains a total of 8 rows, this should work fine.
Add another rank column next to the existing one and put another expression in that one which takes the value from rank (rowcount?) and divide it by 8. Then make the old rank column invisible.
Are you absolutely certain that using RowNumber("NameOfOrganizationGroup") doesn't work?
Click on the matrix, click the upper-left corner selection box to select the entire thing, then right-click on the selection border and get properties. Switch to the Groups tab and look at the names of the groups in the Rows section. That's what goes in the scope of the RowNumber() function.
If you already know this and tried it, my apologies—I didn't mean to assume you didn't know. It's just not 100% clear from your question that this is not the solution.
I got it by using a windowed function in the SQL query, this counts the row correctly within the column set.
dense_rank() over (partition by mgr.employee_sk order by e.employee_sk) as row_format
where mgr.employee_sk is my Lvl 2 Row Group, and e.employee_sk is my Lvl 3 Row Group (the detail level).
Then the SSRS expression then refers to this column from the query. To avoid it aggregating I used a min function, and to avoid it not displaying for rows that don't have data in all columns of the column group I specified the scope as my Level 3 Row Group.
=Iif(min(Fields!row_format.Value, "Employee") mod 2 = 1, "white", "aliceblue")