I am a PowerBI newbie and I have been playing with DAX functions, more specifically, the RANKX function. Here is my data set:
+----------+-------------------------------------+-----------------+----------+
| Category | Sub Category | Date | My Value |
+----------+-------------------------------------+-----------------+----------+
| A | A1 | 2018-01-01 | 2 |
| A | A2 | 2018-01-02 | 4 |
| A | A3 | 2018-01-03 | 6 |
| A | A4 | 2018-01-04 | 6 |
| B | B1 | 2018-01-05 | 21 |
| B | B2 | 2018-01-06 | 22 |
| B | B2 | 2018-01-07 | 23 |
| C | C1 | 2018-01-08 | 35 |
| C | C2 | 2018-01-09 | 35 |
| C | C3 | 2018-01-10 | 35 |
+----------+-------------------------------------+-----------------+----------+
And below is my code:
Rank all rows as Column =
RANKX(
'Table',
'Table'[My Value]
)
Unfortunately, I am getting the following error:
A single value for column 'My Value' in table 'Table' cannot be
determined. This can happen when a measure formula refers to a column
that contains many values without specifying an aggregation such as
min, max, count, or sum to get a single result.
Any help would be greatly appreciated.
Thanks
There is nothing wrong with your formula, you just put it in a wrong place.
There are 2 ways you can write DAX formulas in PowerBI:
as a calculated column
as a measure
The difference is critical, you need to learn it if you want to use PowerBI.
The formula you wrote is for calculated columns. If you create it as a measure, you will get an error. To fix the problem, go to tab "Model", click "New Column", paste your code and it should work.
If you need RANKX as a measure, Chrisoffer has given you a good answer.
Create a mesure to sum "My value" column:
Sum value = SUM(Table[My value])
Then use this measure to get your rank:
Rank all rows as Column =
RANKX(ALL(Table);[Sum value])
This will give you the rank of each sub category.
Related
My Excel sheet has a table that copies data from an SQL database. This table has data of the usage of dies by machines from day 1 till today. There are data of multiple machines in the table.
------------------------------------------
| Machine | Date | Die ID | Usage |
------------------------------------------
| A1 | 20171215 | AAA | 100 |
| A1 | 20171216 | AAA | 150 |
| A1 | 20171217 | AAA | 80 |
.
.
.
| A1 | 20180105 | AAA | 200 |
| B2 | 20171220 | BBB | 500 |
| B2 | 20171221 | BBB | 230 |
.
.
.
| B2 | 20180105 | BBB | 410 |
------------------------------------------
Now I would like to add another table that gets the total usage of a die from a specific point of date (Last Service Date) until today.
---------------------------------------------------------------------------
| Machine | Die ID | Last Service Date | Today | Accumulative Usage |
---------------------------------------------------------------------------
| A1 | AAA | 25/12/2017 | 5/1/2018 | |
---------------------------------------------------------------------------
| B2 | BBB | 1/1/2018 | 5/1/2018 | |
---------------------------------------------------------------------------
Machine is keyed in based on SQL table and Die ID is based on the SQL table.
This Last Service Date is obtained from another table & Today is using latest date formula.
All formulas are written in VBA and copied as values. Now I'm having issues in coming up with the formula for Accumulative Usage.
Starting small using the formula:
=SUM(Table10[Usage])
will only give me the total for the entire column (including data from machine A1 and B2) which is not what I want.
Is there anything I can add to this formula to not only have it calculate the sum based on name of Die ID, but also based on the range set by Last Service Date? Or do I need to use another formula entirely?
The SUMIF function should do what you are looking for. Consider your first request (sum based on Die ID), you can use:
=SUMIF(Table10[Die ID],"=AAA",Table10[Usage])
You can then elaborate that for date range as well.
I'm using Business Objects to construct a simple report on whether a unit is on or off for a given day. When constructing a vertical table, the data is correct and looks like such:
Unit ID | Status | Date
1 | On | 2016-09-10
1 | On | 2016-09-11
1 | Off | 2016-09-12
2 | Off | 2016-09-10
2 | Off | 2016-09-11
2 | On | 2016-09-12
However the cross table I've created, with columns of "date" and rows of "Unit ID" is duplicating Unit ID and having an entire row of 'On' followed by an entire row of 'Off' like:
____| 2016-09-10 | 2016-09-11 | 2016-09-12
1 | On | On | On
1 | Off | Off | Off
2 | On | On | On
2 | Off | Off | Off
instead of what it should be as:
____| 2016-09-10 | 2016-09-11 | 2016-09-12
1 | On | On | Off
2 | Off | Off | On
Any suggestions as to why it's doing this? The table isn't particularly useful if it has these duplicate rows and I can't understand why it's resulting in this odd table.
Turns out what happened is the "Status" field was a dimension type, but the cross table requires the data field to be a measure type. Simply making a new variable that was a measure equal to "Status" solved the issue.
I have a two tables call RFS and RFS_History.
RFS_id | name
--------+--------
12 | xx
14 | yy
15 | zz
figure 1 :RFS table
RFS_id | gate | End | start
--------+-------+--------+-------
12 | aa | 19/02 | 20/03
12 | bb | 30/01 | 12/08
12 | cc | 30/01 | 12/08
13 | aa | 30/01 | 12/08
12 | dd | 30/01 | 12/08
figure 2 :RFS history
My initial query is a select * query to get information where FRSname ='xx'
SELECT * FROM RFS, RFSHistory
WHERE RFSname="xx" And RFShistory.RFS_ID=RFS.RFS_ID
result is:
RFS_id | gate | End | start
--------+-------+--------+-------
12 | aa | 19/02 | 19/01
12 | bb | 12/04 | 12/02
12 | cc | 20/03 | 12/03
12 | dd | 30/09 | 12/08
figure 3
however I want to get a result like bellow format :
RFS_id | gate_aa | gate_bb | gate_cc | gate_dd
----------------------------------------------
12 | 30 days | 60dyas | 8days | 18days
gate_aa is duraion and it gets from start - end date. Please help me to write single query to get this result.
Use datediff() to get date difference and Pivot() to convert row into cloumn
like here in your case gate wise column
Sample Syntax
SELECT DATEDIFF(day,'2008-06-05','2008-08-05') AS DiffDate
You can use the below query for get the difference b/w dates
SELECT RFS.ID,(RFS_HISTORY.end_t-RFS_HISTORY.start_t) AS DiffDate,gate FROM RFS, RFS_HISTORY
WHERE name='aa' And RFS_HISTORY.ID=RFS.ID group by RFS.ID,gate,RFS_HISTORY.end_t,RFS_HISTORY.start_t
I think you want to convert rows into columns on the values. This can be done with the help of pivoting.
SELECT * FROM RFS, RFSHistory
pivot for columname on [values]
I actually forgot the syntax but you can google it
I have a report in reporting services. In this report, I am displaying the Top N values. But my Grand Total is displaying the sum of all the values.
Right now I am getting something like this.Here N = 2
+-------+------+-------------+
| Area |ID | Count |
+-------+------+-------------+
| - A | | 4 |
| | a1 | 1 |
| | b1 | 1 |
| | c1 | 1 |
| | d1 | 1 |
| | | |
| - B | | 3 |
| | a2 | 1 |
| | b2 | 1 |
| | c2 | 1 |
| | | |
|Grand | | 10 |
|Total | | |
+-------+------+-------------+
The correct Grand Total should be 7 instead of 10. A and B are toggle items(You can expand and contract)
How can I display the correct Grand Total using Top N filter?
I also want to use the filter in the report and not in the SQL query.
You should use the filter on the Dataset. Filtering the report object itself only turns off the items (rows, for example) visibility. The item / row itself will still be part of the group and will be used for calculations.
I found a way to solve my question. As Ido said I worked on the dataset. I am using Analysis Cube. So in this cube I created a Named Set Calculation.
In this set I used the TopCount() function. It filters out the TOP N values where N can be integer according to your choice.
So the final Named Set in this case is :-
TopCount([Dim Area].[Area].[Area], 2, ([Measures].[Count]))
This will give you Grand total of Top N filtered values.
I am using Microsoft SQL Server 2008.
I have a table that looks something like this:
|======================================================|
| RespondentId | QuestionId | AnswerValue | ColumnName |
|======================================================|
| P123 | 1 | Y | CanBathe |
|------------------------------------------------------|
| P123 | 2 | 3 | TimesADay |
|------------------------------------------------------|
| P123 | 3 | 1.00 | SoapPrice |
|------------------------------------------------------|
| P465 | 1 | Y | CanBathe |
|------------------------------------------------------|
| P465 | 2 | 1 | TimesADay |
|------------------------------------------------------|
| P465 | 3 | 0.99 | SoapPrice |
|------------------------------------------------------|
| P901 | 1 | N | CanBathe |
|------------------------------------------------------|
| P901 | 2 | 0 | TimesADay |
|------------------------------------------------------|
| P901 | 3 | 0.00 | SoapPrice |
|------------------------------------------------------|
I would like to flip the rows to be columns so that this table looks like this:
|=================================================|
| RespondentId | CanBathe | TimesADay | SoapPrice |
|=================================================|
| P123 | Y | 3 | 1.00 |
|-------------------------------------------------|
| P465 | Y | 1 | 0.99 |
|-------------------------------------------------|
| P901 | N | 0 | 0.00 |
|-------------------------------------------------|
(the example data here is arbitrarily made up, so its silly)
The source table is a temp table with approximately 70,000 rows.
What SQL would I need to write to do this?
Update
I don't even know if PIVOT is the right way to go.
I don't know what column to PIVOT on.
The documentation mentions <aggregation function> and <column being aggregated> and I don't want to aggregate anything.
Thanks in advance.
It, is required to use an aggregate function if you use PIVOT. However, since your (RespondentId, QuestionId) combination is unique, your "groups" will have only one row, so you can use MIN() as an aggregate function:
SELECT RespondentId, CanBathe, TimesADay, SoapPrice
FROM (SELECT RespondentId, ColumnName, AnswerValue FROM MyTable) AS src
PIVOT (MIN(AnswerValue) FOR ColumnName IN(CanBathe, TimesADay, SoapPrice)) AS pvt
If a group only contain one row, then MIN(value) = value, or in other words: the aggregate function becomes the identity function.
See if this gets you started. Used to have to use CASE statements to make that happen but it looks like some inkling of PIVOT is in SQL Server now.
PIVOT is a start, but the thing with sql queries is that you really need to know what columns to expect in the result set before writing the query. If you don't know this, the last time I checked you have to either resort to dynamic sql or allow the client app that retrieves the data to do the pivot instead.