MDX : get members from a subselect (FILTER BY in MDX+) - iccube

I've got the following MDX statement:
WITH
MEMBER [Measures].[ist] AS __get_time_member__
SELECT
// Measures
{[Measures].[ist],[Measures].[soll]} ON 0,
// Rows
FROM [Finance]
FROM ( SELECT [Time].[Time].[month].&[2018-04-01] on 0 from [Finance]
or in MDX+
FILTERBY [Time].[Time].[month].&[2018-04-01]
How can I get in the calculated measure, [ist], the time member defined in the subselect ?

In MDX+ you've a couple of functions that allow to get some informations from the slicer and the subselect :
ContextMember - This works like currentMember including the slicer and subselect
GetFilterInfo(hierarchy) - extracts only from slicer and subselect
In your case you can use GetFilterInfo function with the hierarchy you're looking for.
I guess is just a question of playing around with these functions.
PS: We could easily add GetSlicerInfo and GetSubselectInfo if needed.

Related

Drools, graph traversal, query to find root nodes

I have a Java-side class with essential behaviour like:
declare Datum
description: String
broader: List <Datum>
narrower: List <Datum>
end
I want to write
query rootDatumsFor(Datum datum)
that provides a list of the root datums - that is, work "up" the broader property and return a list of each datum that has an empty broader list.
I am getting totally confused how to write this - mainly because of the negation involved.
I think I want something like
query rootDatumsFor( Datum datum )
not Datum() from $datum.broader
or
rootDatumsFor( $datum.broader )
end
But I am getting confused on both parts. If there are no broader terms, which the not should detect, how do I "return" the current value of $datum? I feel each part wants a $result and I want to do a $result: $datum but that isn't valid.
And I'm not certain how to do the recursion. Should I have rootDatumsFor(datum, result) and do it via binding?
I've seen examples that do things likes Datum( this == $datum) but that doesn't seem to be accepted when I try it.
Any assistance, whilst I keep re-reading the docn to find a little clue how to proceed, would be much appreciated.
To find all Datum facts with an empty broaderlist, all you have to do is
query rootDatumsFor( Datum $datum )
$datum: Datum( broader.size() == 0 )
end

Filter using edges / vertices

I try to filter nodes :
user = g.v(42);
g.idx('comparisons')[[id:Neo4jTokens.QUERY_HEADER + '*']]
.filter{
if (it.out('COMPARED_VALUE1').in('VOTED').in('VOTES').next().equals(user))
{
return true;
}
return false;
}.count();
I don't really understand how pipes works, but I understand that the next() breaks something in the filter "loop".
I should get 2 results, but I get none.
Regards,
I might need to amend my answer as I could require more specifics on what you are trying to achieve (as #Michael also requested), but if you think your problem is with next(), then consider the following:
user = g.v(42);
g.idx('comparisons')[[id:Neo4jTokens.QUERY_HEADER + '*']]
.filter{it.out('COMPARED_VALUE1').in('VOTED').in('VOTES').next().equals(user)}.count();
First, note above that your filter closure can immediately reduce to that (which will yield the same error, of course). Given that filter closure you are assuming that a user vertex will come out of the pipeline when you next(). That may not be the case. As such, I would re-write the filter closure as:
user = g.v(42);
g.idx('comparisons')[[id:Neo4jTokens.QUERY_HEADER + '*']].filter{
def p = it.out('COMPARED_VALUE1').in('VOTED').in('VOTES')
p.hasNext() ? p.next().equals(user) : false
}.count();
That should likely solve your problem right there given the assumption that you only need to evaluate the first item in the pipeline p which is effectively what you were doing before. I wonder if you couldn't simply use except/retain pattern here to get your answer as it is a bit less convoluted:
user = g.v(42);
g.idx('comparisons')[[id:Neo4jTokens.QUERY_HEADER + '*']]
.out('COMPARED_VALUE1').in('VOTED').in('VOTES').retain([user])
.count();
Hopefully something here puts on you on the right track to your answer.
What do you want to achieve?
Sorry my gremlin knowledge is close to zero these days.
In cypher it would probably look like this
START user=node(42), comp=node:comparisons("id:*")
MATCH comp-[:COMPARED_VALUE1]->()<-[:VOTED*2]-(user)
RETURN count(*)

use aggregate functions in the WHERE clause (Neo4j)

How do I select all nodes that are connected to node(2) [from] with more than one path?
START from=node(2)
MATCH p=from-->to
where count(p) > 1
return from,to
To Neo4J team : Any plans to implement Count/Having functions?
great job so far with the product!
actually found the solution combining the 'WITH' keyword
START from=node(*)
MATCH p=from-->to
WITH from as from , to as to, count(p) as paths
WHERE paths >1
RETURN to,paths

Get nth element of a collection in Cypher

Using Cypher 1.8, there are some functions working on collections and returning a single element:
HEAD( expression ):
START a=node(2)
RETURN a.array, head(a.array)
LAST( expression ):
START a=node(2)
RETURN a.array, last(a.array)
However, I could not find a function to return the nth element of a collection. What am I missing?
There's no good way to do that at the moment. Please submit a feature request at https://github.com/neo4j/neo4j
I've seen people do head(tail(tail(tail(coll)))), and while it's probably acceptably fast, it still makes me a little ill to see in a query, especially if you're talking about the 17th element or worse.
Example:
http://console.neo4j.org/r/bbo6o4
Update:
Here's a way to do it using reduce and range. It makes it so you can give a parameter for nth at least, even though it still makes me cringe:
start n=node(*)
with collect(n) as allnodes
return head(reduce(acc=allnodes, x in range(1,3): tail(acc)));
http://console.neo4j.org/r/8erfup
Update 2 (8/31/2013):
The new collection syntax is now merged into 2.0 and will be theoretically be a part of M05! So, you'll be able to do:
start n=node(*)
with collect(n) as allnodes
return allnodes[3]; // or slices, like [1..3]
I'll add a link to the snapshot documentation when it gets updated.
I've just come across this old question, and for the benefit of anyone else recently coming across it... it seems the list support has improved.
From the Cypher 4 list docs:
Cypher has comprehensive support for lists.
^ Sidenote: I think that's list comprehensions pun? ;-)
They go on to give an example showing how you'd access the n'th element of a list:
To access individual elements in the list, we use the square brackets again. This will extract from the start index and up to but not including the end index.
... we’ll use the range function. It gives you a list containing all numbers between given start and end numbers. Range is inclusive in both ends.
RETURN range(0, 10)[3]
^ returns "3"
Currently, with the release of APOC Procedures 3.3.0.2 you can use aggregation functions.
This way, you can do thinks like:
create (:Node {node_id : 1}),
(:Node {node_id : 2}),
(:Node {node_id : 3});
match(n:Node)
with n order by n.node_id
// returns {"node_id":2}
return apoc.agg.nth(n, 1);
or:
match(n:Node)
with n order by n.node_id
// returns {"node_id":1}
// you can also use apoc.agg.last
return apoc.agg.first(n);
To work with lists UNWIND the list first:
with ['fist', 'second', 'third'] as list
unwind list as value
// returns 'second'
return apoc.agg.nth(value, 1);

How to stop evaluating if the first condion has been passed

I try to evaluate a field in my report but it fails every time :
= IIf(Fields!lectcrs_hrs.IsMissing,
Round(Fields!lectcrs_fee.Value * "1.00", 2),
Round(Fields!lectcrs_fee.Value * Fields!lectcrs_hrs.Value, 2))
in the case of Fields!lectcrs_hrs.IsMissing = true my field is empty and i find that the reason that the second case Round(Fields!lectcrs_fee.Value * Fields!lectcrs_hrs.Value, 2) contains a missing field Fields!lectcrs_hrs .why it checks the second case if it passes the first one !
How to fix this problem ?
The behavior you are looking for is called "short-circuiting" and, unfortunately, the IIf function in Visual Basic does not offer that. The reason being is that IIf() is a ternary function and, as such, all arguments passed into it are evaluated before the function call occurs. A ternary operator (If() in VB 9+), on the other hand, does support conditional evaluation. However, I do not believe that the If() operator can be used as a part of an expression in SSRS.
Given the fact that you are trying to use a field which may or may not exist at run time, I suggest that you create a custom function in your report to handle the proper checking and return values. For reference, take a look at this blog post, which covers the same scenario.

Resources