I am trying to write an MDX query which selects top 100 rows by dimension or measure value.
Fragment on a query
NonEmpty([Domain].[Domain].[Domain].Members , { [Measures].[Total - Domains] } )
I can use topcount and get top 100 rows by "order_count" measure successfully:
topcount(NonEmpty([Domain].[Domain].[Domain].Members , { [Measures].[Total - Domains] } ), 100, [Measures].[order_count])
However, when i try to do that on the dimension value, it does not seem to work properly it seems like it is not doing sorting operation):
topcount(NonEmpty([Domain].[Domain].[Domain].Members , { [Measures].[Total - Domains] } ), 100, [Domain].[Domain].[Value])
I have read that topcount expects numeric expression to sort and my domain value is a string, so I have tried using head() and order(), but I still get incorrect results.
UPDATE: Is seems that i needed to use [Domain].[Domain].properties('Value') instead of [Domain].[Domain].[Value]
SOLVED
Related
I have a simple MDX query that filters data to one of two Status values:
SELECT
NON EMPTY
{ [confidentialstring].Members }
ON COLUMNS,
NON EMPTY
{ [APMWORDER].[LEVEL01].Members *
[APMSTDOPR].[LEVEL01].Members *
[AWOUSTAT].[LEVEL01].Members *
[ANOTIFCTN].[LEVEL01].Members
}
ON ROWS
FROM [APM_CP002/APM_CP002_QX006]
WHERE { ( [AWOUSTAT].[E0001] ), ( [AWOUSTAT].[E0002] ) }
But I also need [AWOUSTAT] in my table, to see which status value is actually applicable.
However MDX throws an error if I add it: 'You may not use the same dimension on different axes'. I understand this in principle but not in this application ('filter' is not an axis to me...)
How can I resolve this, without having to create two queries?
Thanx!
Since you cannot have the same dimension on rows and in where clause, and you want to see [AWOUSTAT].[E0001]] , [AWOUSTAT].[E0002] , in your table, I think you could try something like this to start:
SELECT
NON EMPTY
{ [confidentialstring].Members }
ON COLUMNS,
NON EMPTY
{ ( [AWOUSTAT].[E0001]] ), ( [AWOUSTAT].[E0002] ) }
ON ROWS
FROM [APM_CP002/APM_CP002_QX006]
A common technique is to replace the WHERE clause with a FROM clause.
Sample using adventure works:
SELECT
NON EMPTY
{[Measures].[Order Count]} ON COLUMNS
,NON EMPTY
{[Date].[Day of Month].[Day of Month].ALLMEMBERS}
ON ROWS
FROM
(
SELECT
{[Date].[Fiscal Year].&[2011]} ON COLUMNS
FROM [Adventure Works]
)
In the above example, it is equivalent to having a WHERE clause of the Fiscal Year = 2011.
You can see a similar output, whenever you use the SSMS Cube Browser to build queries.
It may look strange to replace WHERE with FROM, BUT, in the in most cases with the Cube, it does provide the required output.
I'm currently trying to figure out how to get a count of unique records to display using DJ.js and D3.js
The data set looks like this:
id,name,artists,genre,danceability,energy,key,loudness,mode,speechiness,acousticness,instrumentalness,liveness,valence,tempo,duration_ms,time_signature
6DCZcSspjsKoFjzjrWoCd,God's Plan,Drake,Hip-Hop/Rap,0.754,0.449,7,-9.211,1,0.109,0.0332,8.29E-05,0.552,0.357,77.169,198973,4
3ee8Jmje8o58CHK66QrVC,SAD!,XXXTENTACION,Hip-Hop/Rap,0.74,0.613,8,-4.88,1,0.145,0.258,0.00372,0.123,0.473,75.023,166606,4
There are 100 records in the data set, and I would expect the count to display 70 for the count of unique artists.
var ndx = crossfilter(spotifyData);
totalArtists(ndx);
....
function totalArtists(ndx) {
// Select the artists
var totalArtistsND = dc.numberDisplay("#unique-artists");
// Count them
var dim = ndx.dimension(dc.pluck("artists"));
var uniqueArtist = dim.groupAll();
totalArtistsND.group(uniqueArtist).valueAccessor(x => x);
totalArtistsND.render();
}
I am only getting 100 as a result when I should be getting 70.
Thanks a million, any help would be appreciated
You are on the right track - a groupAll object is usually the right kind of object to use with dc.numberDisplay.
However, dimension.groupAll doesn't use the dimension's key function. Like any groupAll, it looks at all the records and returns one value; the only difference between dimension.groupAll() and crossfilter.groupAll() is that the former does not observe the dimension's filters while the latter observes all filters.
If you were going to use dimension.groupAll, you'd have to write reduce functions that watch the rows as they are added and removed, and keeps a count of how many unique artists it has seen. Sounds kind of tedious and possibly buggy.
Instead, we can write a "fake groupAll", an object whose .value() method returns a value dynamically computed according to the current filters.
The ordinary group object already has a unique count: the number of bins. So we can create a fake groupAll which wraps an ordinary group and returns the length of the array returned by group.all():
function unique_count_groupall(group) {
return {
value: function() {
return group.all().filter(kv => kv.value).length;
}
};
}
Note that we also have to filter out any bins of value zero before counting.
Use the fake groupAll like this:
var uniqueArtist = unique_count_groupall(dim.group());
Demo fiddle.
I just added this to the FAQ.
I have an MDX query where I am using a Parent-Child hierarchy where a property on any level have a specific values.
Now I want to take create a sets, that have each of these specific values and subtract them from each other
The query I have looks like this:
WITH
SET [OMS] AS
{
DESCENDANTS(
FILTER([ReportHierarchy].[Hierarchy].MEMBERS,
[ReportHierarchy].[Hierarchy].Properties( "Sum Code" )="OMS")
,,SELF)
}
SET [VF] as {
DESCENDANTS(
FILTER([ReportHierarchy].[Hierarchy].MEMBERS,
[ReportHierarchy].[Hierarchy].Properties( "Sum Code" )="VF")
,,SELF)
}
SELECT
{
[Measures].[Amount],
[Measures].[Budget Amount]
} ON COLUMNS,
{
[OMS],
[VF]
}
on ROWS
FROM
Finance
WHERE
[ReportHierarchy].[Hierarchy Name].&[Income and Balance]
which returns this result:
Amount Budget Amount
Nettoomsætning -126418831.1 -308192540.75
Vareforbrug 65415924.25 159307880.45
Now I want to do a calulation which subtracts SET [VF] from set [OMS]...
Anyone have any suggestions?
you need WITH MEMBER to create a new item in your left-most column. This new item can be set up to calculate the value of one item minus another. Here's a similar situation from an old query I wrote years ago:
WITH MEMBER [Actual Time].[MySubtraction]
AS '[Actual Time].[Week].[Week 5] - [Actual Time].[Week].[Week 4]', SOLVE_ORDER=80
SELECT {
[Location].[All Location].[Blah Blah]
} ON ROWS,{
[Actual Time].[Week].members,
[Actual Time].[MySubtraction]
}
ON COLUMNS FROM [CubeName]
WHERE ([Measures].[Whatever])
My MDX is getting rusty these days, so I have not tried to give you the exact query you need, sorry. Have a look at the documentation for WITH MEMBER to learn more.
Importing this dataset as a table:
https://data.cityofnewyork.us/Housing-Development/Registration-Contacts/feu5-w2e2#revert
I use the following query to perform an aggregation and then attempt to sort in descending order based on the reduction field. My intention is sort based on the count of that field or to have the aggregation create a second field called count and sort the grouping results in descending order of the reduction array count or length. How can this be done in rethinkdb?
query:
r.table("contacts").filter({"Type": "Agent","ContactDescription" : "CONDO"}).hasFields("CorporationName").group("CorporationName").ungroup().orderBy(r.desc('reduction'))
I don't quite understand what you're going for, but does this do what you want? If not, what do you want to be different in the output?
r.table("contacts")
.filter({"Type": "Agent","ContactDescription" : "CONDO"})
.hasFields("CorporationName")
.group("CorporationName")
.ungroup()
.merge(function(row){ return {count: row('reduction').count()}; })
.orderBy(r.desc('count'))
You are almost there:
r.table("contacts").filter({"Type": "Agent","ContactDescription" : "CONDO"}).hasFields("CorporationName").group("CorporationName").count().ungroup().orderBy(r.desc('reduction'))
See that .count()? That is a map-reduce operation to get the count of each group.
I haven't tested the query on your dataset. Please comment in case you had problems with it.
EDIT:
If you want to add a count field and preserve the original document, you need to use map and reduce. In your case, it should be something like:
r.table("contacts").filter({"Type": "Agent","ContactDescription" : "CONDO"})
.hasFields("CorporationName")
.group("CorporationName")
.map(r.row.merge({count:1}))
.reduce(function(left, right){
return {
count: left('count').add(right('count')),
<YOUR_OTHER_FIELDS>: left('<YOUR_OTHER_FIELDS>'),
...
};
})
.ungroup().orderBy(r.desc(r.row('reduction')('count')))
EDIT:
I am not sure if this can do the trick, but it is worth a try:
.reduce(function(left, right){
return left.merge({count: left('count').add(right('count'))})
})
I wan't to create report from the result of an olap Query, the result type is a cellSet. Does any one have any idea.
thx
The easiest way to print out results is by using one of the built-in formatter. There is an example available here.
To programmatically iterate over the axis and positions of a CellSet, you need to iterate over each axis, then each position on the axis. A simple CellSet with two axis (with ordinals known in advance) can be iterated over like so:
// Iteration over a two-axis query
for (
Position axis_0
: data.getAxes().get( Axis.ROWS.axisOrdinal() ).getPositions())
{
for (
Position axis_1
: data.getAxes().get(Axis.COLUMNS.axisOrdinal()).getPositions())
{
Object value =
data.getCell(axis_0, axis_1)
.getValue();
}
}