Azure Application Insights Query - How to calculate percentage of total - azure

I'm trying to create a row in an output table that would calculate percentage of total items:
Something like this:
ITEM | COUNT | PERCENTAGE
item 1 | 4 | 80
item 2 | 1 | 20
I can easily get a table with rows of ITEM and COUNT, but I can't figure out how to get total (5 in this case) as a number so I can calculate percentage in column %.
someTable
| where name == "Some Name"
| summarize COUNT = count() by ITEM = tostring( customDimensions.["SomePar"])
| project ITEM, COUNT, PERCENTAGE = (C/?)*100
Any ideas? Thank you.

It's a bit messy to create a query like that.
I've done it bases on the customEvents table in AI. So take a look and see if you can adapt it to your specific situation.
You have to create a table that contains the total count of records, you then have to join this table. Since you can join only on a common column you need a column that has always the same value. I choose appName for that.
So the whole query looks like:
let totalEvents = customEvents
// | where name contains "Opened form"
| summarize count() by appName
| project appName, count_ ;
customEvents
// | where name contains "Opened form"
| join kind=leftouter totalEvents on appName
| summarize count() by name, count_
| project name, totalCount = count_ , itemCount = count_1, percentage = (todouble(count_1) * 100 / todouble(count_))
If you need a filter you have to apply it to both tables.
This outputs:

It is not even necessary to do a join or create a table containing your totals
Just calculate your total and save it in a let like so.
let totalEvents = toscalar(customEvents
| where timestamp > "someDate"
and name == "someEvent"
| summarize count());
then you can simply add a row to your next table, where you need the percentage calcualtion by doing:
| extend total = totalEvents
This will add a new column to your table filled with the total you calculated.
After that you can calculate the percentages as described in the other two answers.
| extend percentages = todouble(count_)*100/todouble(total)
where count_ is the column created by your summarize count() which you presumably do before adding the percentages.
Hope this also helps someone.

I think following is more intuitive. Just extend the set with a dummy property and do a join on that...
requests
| summarize count()
| extend a="b"
| join (
requests
| summarize count() by name
| extend a="b"
) on a
| project name, percentage = (todouble(count_1) * 100 / todouble(count_))

This might work too:
someTable
| summarize count() by item
| as T
| extend percent = 100.0*count_/toscalar(T | summarize sum(count_))
| sort by percent desc
| extend row_cumsum(percent)

Related

How can I combine duplicates of 1 column, then have multiple results in the same row of another column?

I am very new to kql, and i am stuck on this query. I am looking to have query display which users have had sign-ins from different states. I created this query, but i do not know how to count the results in the column "names".
SigninLogs
| project tostring(LocationDetails.state), UserDisplayName
| extend p =pack( 'Locations', LocationDetails_state)
| summarize names = make_set(p) by UserDisplayName
This generates a column "names" with a row like so:
[{"Locations":"Arkansas"},{"Locations":"Iowa"},{"Locations":""}]
Here is a simple query that grabs all sign-ins from users and another column with the locations.
SigninLogs
| where ResultType == "0"
| summarize by UserDisplayName, tostring(LocationDetails.state)
Is there a way to combine the duplicates of users column, and then display each location in the second? If so, could i count each location in order to filter by where location is > 1?
I am looking to have query display which users have had sign-ins from different states
Assuming I understood your question correctly, this could work (using array_length()):
SigninLogs
| project State = tostring(LocationDetails.state), UserDisplayName
| summarize States = make_set(State) by UserDisplayName
| where array_length(States) > 1 // filter users who had sign-ins from *more than 1 state*

Making Switch function return a column in a table and not a measure (PowerBI DAX)

What I'm trying to do is to change measures using slicers in Power BI Desktop. I have found some examples of people who have done that (for instance this ) .
What they do is that they create a table where there are ID and Measure names. The 'Measure names' column of this table will be used as field value in the filter of the visualization. Then, they create a switch function that, given a certain value in the filter, switch the value in the filter to a measure.
You can see an example below:
Measure Value = SWITCH(
MIN('Dynamic'[Measure ID]) ,
1,[Max Temp],
2,[Min Temp],
3,[Air Pressure],
4,[Rainfall],
5,[Wind Speed],
6,[Humidity]
)
Where 'Dynamic' is a group containing a measure ID and a Measure name:
Dynamic:
Measure ID | Measure Name
1 | Max Temp
2 | Min Temp
3 | Air Pressure
4 | Rainfall
5 | Wind Speed
6 | Humidity
All of the 'Measure Name' are measures as well.
My problem is: I have too many columns (400!) and I cannot turn them into measures one by one. It will take days. I was thinking that maybe I could use the switch function so that it returns the column in the table and NOT the corresponding measure. However I cannot just insert
'Name of the table'['Name of the column'] in the switch function as result parameter.
Does anyone know how to make the function Switch return a column and not a measure? (Or any other suggestion)
DAX doesn't work well for lots of columns like this, so I'd suggest reshaping your data (in the query editor) by unpivoting all those columns you want to work with so that instead of a table that looks like this
ID | Max Temp | Min Temp | Air Pressure | Rainfall | Wind Speed | Humidity
---+----------+----------+--------------+----------+------------+----------
1 | | | | | |
...
you'd unpivot all those data columns so it looks more like this:
ID | ColumnName | Value
---+--------------+-------
1 | Max Temp |
1 | Min Temp |
1 | Air Pressure |
1 | Rainfall |
1 | Wind Speed |
1 | Humidity |
...
Then you can create a calculated table, Dynamic, to use as your slicer:
Dynamic = DISTINCT ( Unpivoted[ColumnName] )
Now you can write a switching measure like this:
SwitchingMeasure =
VAR ColName = SELECTEDVALUE ( Dynamic[ColumnName] )
RETURN
CALCULATE ( [BaseMeasure], Unpivoted[ColumnName] = ColName )
where [BaseMeasure] is whatever aggregation you're after, e.g., SUM ( TableName[Value] ).

Trying to calculate the average on a count of records in my query results

I'm trying to create a query in Application Insights that can show me the absolute and average number of messages in conversations over a particular time period. I'm using the LUIS trace example to get the context+LUIS information, which is where I'm pulling the conversationID from. I can get a table showing the number of messages per conversation, but I would also like to have a average number of messages for the data set. Either static average or rolling average (by pulling in timestamp) would be fine. I can get this value by doing a second summarize statement, but then I lose the granularity from the first. Here is my query.
requests
| where url endswith "messages"
| where timestamp > ago(30d)
| project timestamp, url, id
| parse kind = regex url with *"(?i)http://"botName".azurewebsites.net/api/messages"
| join kind= inner (
traces | extend id = operation_ParentId
) on id
| where message == "LUIS"
| extend convID = tostring(customDimensions.LUIS_botContext_conversation_id)
| order by timestamp desc nulls last
| project timestamp, botName, convID
| summarize messages=count() by conversation=convID
This gives me a table of conversation IDs with the message count for each conversation. I would also like to see the average number of messages per conversation. For example, if I have 4 conversations with 100 messages total, I want to see that the average is 25. I can get this result by doing a second summarize statement | summarize messages=sum(messages), avgMessages=avg(messages), but then of course I can no longer see the individual conversations. Is there any way to see both in the same table?
You can write 2 queries, one for "gives me a table of conversation IDs with the message count for each conversation", and another for " the average number of messages per conversation". And consider use Let statement for your query.
The tricky here is that, in both of the 2 queries, after the summarize statement, add this line of code at the end, like | extend myidentifier="aaa" .
Then you can join the 2 queries by using myidentifier.
I couldn't figure out how to do this without losing granularity from the first list (i.e. I couldn't figure out how to calculate average per period e.g. day), but the following query does at least get me the average across whatever timestamp filter I set, which ultimately gets me at the data I was looking for.
requests
| where url endswith "messages"
| where timestamp > ago(30d)
| project timestamp, url, id
| parse kind = regex url with *"(?i)http://"botName".azurewebsites.net/api/messages"
| join kind= inner (
traces | extend id = operation_ParentId
) on id
| where message == "LUIS"
| extend convID = tostring(customDimensions.LUIS_botContext_conversation_id)
| order by timestamp desc nulls last
| project timestamp, botName, convID
| summarize messages=count() by conversation=convID
| summarize conversations=count(), messageAverage=avg(messages)

How to zero-fill charts/bins in Application Insights Analytics

I'm trying to plot an area chart of one sum/count metric over time in Application Insights Analytics:
customEvents
| where timestamp > ago(7d)
| summarize count() by bin(timestamp, 1h)
| render areachart
What I see is that if there is no data in some buckets then chart doesn't drop to 0. Instead two dots are connected and there is perception that there were some data when in fact there were not.
Question - how to get zero-filled area charts (corresponding to red ink chart)?
There are several ways to achieve this.
make-series operator allows to set default value for the periods where no data is present for aggregation:
customEvents
| where timestamp > ago(10m)
| make-series count() default=0 on timestamp in range(ago(10m), now(), 1m)
| render areachart
This will produce zero-filled data array and | render will build the chart accordingly.
If | summarize is preferred, you can create zero-filled range yourself with range operator:
let defaultValue = 0;
range timestamp from floor(ago(10m),1m) to floor(now() + 10m,1m) step 1m
| join kind=leftouter
(
customEvents
| where timestamp > floor(ago(10m),1m) and timestamp < floor(now(),1m)
| summarize Value=count() by bin(timestamp, 1m)
) on timestamp
| project timestamp, value = iff(isnotempty(Value), Value, defaultValue)
| render areachart
Make sure to use join kind=leftouter to have all timestamps from the left side of the join present in output.

Excel: max() of count() with column grouping in a pivot table

I have a pivot table fed from a MySQL view. Each returned row is basically an instantiation of "a person, with a role, at a venue, on a date". The each cell then shows count of person (lets call it person_id).
When you pivot this in excel, you get a nice table of the form:
| Dates -->
--------------------------
Venue |
Role | -count of person-
This makes a lot of sense, and the end user likes this format BUT the requirement has changed to group the columns (date) into a week.
When you group them in the normal way, this count is then applied in columns as well. This is, of course, logical behaviour, but what I actually want is max() of the original count().
So the question: Does anyone know how to have cells count(), but the grouping perform a max()?
To illustrate this, imagine the columns for a week. Then imaging the max() grouped as a week, giving:
Old:
| M | T | W | T | F | S | S ||
--------------------------------------- .... for several weeks
Venue X |
Role Y| 1 | 1 | 2 | 1 | 2 | 3 | 1 ||
New (grouped by week)
| Week 1 | ...
---------------------------
Venue X |
Role Y| 3 | ...
I'm not on my pc, but the steps below should be broadly correct:
You should be able to right click on the date field on pivot table and select group.
Then highlight week, you may have to select year also.
Lastly right click on the count data you already have and expand the summarise by, and select max.

Resources