MDX error trying to compare one hierarchy level to another one - multidimensional-array

I have an MDX issue that I really don't understand with a 5 level hierarchy "SEGMENTATION" : AFFAIRE/NIVEAU 1/ NIVEAU 2/NIVEAU 3/NIVEAU 4
I want to compare "NIVEAU 1" sub-levels weight to "Niveau 1".
For instance, I want to know for each 'NIVEAU 3' members its contributions part for its "NIVEAU 1".
I've tried a bunch of things, but nothing works properly. I don't get the trick and is stucked to :
WITH MEMBER [Measures].[TEST] AS'
iif(ISEMPTY(([Segmentation].[Niveau1], [Measures].[Total])) OR ([Segmentation].[Niveau1],[Measures].[Total]) = 0
, NULL
,[Measures].[Total] / ([Segmentation].[Niveau1], [Measures].[Total])
)'
SELECT NON EMPTY { [Measures].[TEST],[Measures].[Total]} ON COLUMNS
, NON EMPTY { [Segmentation].[Niveau2]}
ON ROWS FROM ( SELECT ( { [Segmentation].[Niveau1].&[8589934592]&[1|DESC111] } ) ON COLUMNS FROM [CUBE]) // Only one "Niveau 1" focus
And I get :
<Niveau 2> TEST Total
SF - C... #Error 25143658
SF - M... #Error 1638913,5
ZZZ ... #Error 90468628
#Error : The EqualTo function expects a string or numeric expression for argument 1. A tuple set expression was used.
The expected result is :
<Niveau 2> TEST Total
SF - C... 21,44% 25143658
SF - M... 1,40% 1638913,5
ZZZ ... 77,16% 90468628
21,4% = 25143658/(25143658+1638913,5+90468628)
What's wrong with my MDX?
Is there a mistake among the dimension or hierarchy set up?

Tuples are written as comma separated lists of members. What you have is a dimension.
Try
[Segmentation].CurrentMember.Parent
Instead of
[Segmentation].[Niveau1]
On your measure definition.
[EDIT] As mentioned in a comment, the goal is a solution that works on all levels. The solution is to use
Ancestor( [Segmentation].CurrentMember, [Segmentation].[Niveau1] )
in the Tuple used in the custom measure definition.

Thanks to nsousa, I'm now using :
WITH MEMBER [Measures].[Total Niveau1] AS'
iif([Segmentation].CURRENTMEMBER.level.ordinal>=2
,(Ancestor([Segmentation].CurrentMember,[Segmentation].[Niveau1] ),[Measures].[Total])
,([Segmentation].CURRENTMEMBER, [Measures].[Total])
)
'
MEMBER [Measures].[TEST] AS'
DIVIDE([Measures].[Societe],[Measures].[Total Niveau1])
',FORMAT_STRING = 'Percent'
SELECT NON EMPTY { [Measures].[TEST],[Measures].[Societe],[Measures].[Total]} ON COLUMNS
, NON EMPTY { [Segmentation].[Niveau3]}
ON ROWS FROM [CUBE]

Related

Build query with aggregate functions in HAVING clause

I am trying to figure out how to have aggregate functions in the having clause with CakePHP's query builder.
Background: the intent is to correct all rows in a table with compound primary-keys (page-ID and URL) such that each page-ID-group has only one default video. There are some groups with no, and some groups with more than one "default" row, which needs to be corrected. I've figured out all the steps – except for this detail.
This is the query that I'm trying to build.
SELECT
video_page_id, video_url
FROM page_video
WHERE
video_page_id IN (
SELECT video_page_id
FROM page_video
GROUP BY video_page_id
HAVING SUM(video_is_default) < 1
)
AND video_order = 0
;
And this is what I have built:
// sub-select: all groups that have too few defaults.
// Returns list of page-IDs.
$qb = $this->getQueryBuilder();
$group_selection = $qb
->select(array(
'video_page_id',
))
->from('page_video')
->group('video_page_id')
->having(array(
'1 >' => $qb->func()->sum('video_is_default'),
))
;
// sub-select: compound-primary-key identifiers of all rows where
// `video_is_default` has to be modified from `0` to `1`.
// Returns list of two columns.
$qb = $this->getQueryBuilder();
$modifiable_selection = $qb
->select(array(
'video_page_id',
'video_url',
))
->from('page_video')
->where(array(
'video_page_id IN' => $group_selection,
'video_order = 0',
))
;
But then I get this exception: Column not found: 1054 Unknown column '1' in 'having clause'
The crux is the HAVING clause. I basically don't know how to combine the aggregate function with the attribute-value properties of an array. Usually, in order to craft lower/greater-than clauses, you write it like this: array('col1 >' => $value). But here, I needed to flip the equation because the complex expression can't fit into an array key. And now the 1 gets interpreted as a column name.
Writing it as a concatenated string doesn't seem to help either.
array(
$qb->func()->sum('video_is_default') .' > 1',
)
Exception: PHP Recoverable fatal error: Object of class Cake\Database\Expression\FunctionExpression could not be converted to string
I know I could do …
SELECT (…), SUM(video_is_default) AS default_sum FROM (…) HAVING default_sum < 1 (…)
… but then the sub-select column count doesn't match anymore.
Exception: ERROR 1241 (21000): Operand should contain 1 column(s)
I feel silly for figuring out the solution so soon after asking the question.
The lt method acccepts complex values as the first parameter.
->having(function($exp, $qb) {
$default_sum = $qb->func()->sum('video_is_default');
return $exp->lt($default_sum, 1);
})

Using Multiple Variables to Reference a Sub-Sub-Sub Field in a Lua Dictionary

I'm new to Lua (like, yesterday new), so please bear with me...
I apologize for the convoluted nature of this question, but I had no better idea of how to demonstrate what I'm trying to do:
I have a Lua table being used as a dictionary. The tuples(?) are not numerically indexed, but use mostly string indices. Many of the indices actually relate to sub-tables that contain more detailed information, and some of the indices in those tables relate to still more tables - some of them three or four "levels" deep.
I need to make a function that can search for a specific item description from several "levels" into the dictionary's structure, without knowing ahead of time which keys/sub-keys/sub-sub-keys led me to it. I have tried to do this using variables and for loops, but have run into a problem where two keys in a row are being dynamically tested using these variables.
In the example below, I'm trying to get at the value:
myWarehouselist.Warehouse_North.departments.department_one["rjXO./SS"].item_description
But since I don't know ahead of time that I'm looking in "Warehouse_North", or in "department_one", I run through these alternatives using variables, searching for the specific Item ID "rjXO./SS", and so the reference to that value ends up looking like this:
myWarehouseList[warehouse_key].departments[department_key][myItemID]...?
Basically, the problem I'm having is when I need to put two variables back-to-back in the reference chain of a value being stored at level N of a dictionary. I can't seem to write it out as [x][y], or as [x[y]], or as [x.y] or as [x].[y]... I understand that in Lua, x.y is not the same as x[y] (the former directly references a key by string index "y", while the latter uses the value being stored in variable "y", which could be anything.)
I've tried many different ways and only gotten errors.
What's interesting is that if I use the exact same approach, but add an additional "level" to the dictionary with a constant value, such as ["items"] (under each specific department), it allows me to reference the value without issue, and my script runs fine...
myWarehouseList[warehouse_key].departments[department_key].items[item_key].item_description
Is this how Lua syntax is supposed to look? I've changed the table structure to include that extra layer of "items" under each department, but it seems redundant and unnecessary. Is there a syntactical change that I can make to allow me to use two variables back-to-back in a Lua table value reference chain?
Thanks in advance for any help!
myWarehouseList = {
["Warehouse_North"] = {
["description"] = "The northern warehouse"
,["departments"] = {
["department_one"] = {
["rjXO./SS"] = {
["item_description"] = "A description of item 'rjXO./SS'"
}
}
}
}
,["Warehouse_South"] = {
["description"] = "The southern warehouse"
,["departments"] = {
["department_one"] = {
["rjXO./SX"] = {
["item_description"] = "A description of item 'rjXO./SX'"
}
}
}
}
}
function get_item_description(item_id)
myItemID = item_id
for warehouse_key, warehouse_value in pairs(myWarehouseList) do
for department_key, department_value in pairs(myWarehouseList[warehouse_key].departments) do
for item_key, item_value in pairs(myWarehouseList[warehouse_key].departments[department_key]) do
if item_key == myItemID
then
print(myWarehouseList[warehouse_key].departments[department_key]...?)
-- [department_key[item_key]].item_description?
-- If I had another level above "department_X", with a constant key, I could do it like this:
-- print(
-- "\n\t" .. "Item ID " .. item_key .. " was found in warehouse '" .. warehouse_key .. "'" ..
-- "\n\t" .. "In the department: '" .. dapartment_key .. "'" ..
-- "\n\t" .. "With the description: '" .. myWarehouseList[warehouse_key].departments[department_key].items[item_key].item_description .. "'")
-- but without that extra, constant "level", I can't figure it out :)
else
end
end
end
end
end
If you make full use of your looping variables, you don't need those long index chains. You appear to be relying only on the key variables, but it's actually the value variables that have most of the information you need:
function get_item_description(item_id)
for warehouse_key, warehouse_value in pairs(myWarehouseList) do
for department_key, department_value in pairs(warehouse_value.departments) do
for item_key, item_value in pairs(department_value) do
if item_key == item_id then
print(warehouse_key, department_key, item_value.item_description)
end
end
end
end
end
get_item_description'rjXO./SS'
get_item_description'rjXO./SX'

Update dictionary key inside list using map function -Python

I have a dictionary of phone numbers where number is Key and country is value. I want to update the key and add country code based on value country. I tried to use the map function for this:
print('**Exmaple: Update phone book to add Country code using map function** ')
user=[{'952-201-3787':'US'},{'952-201-5984':'US'},{'9871299':'BD'},{'01632 960513':'UK'}]
#A function that takes a dictionary as arg, not list. List is the outer part
def add_Country_Code(aDict):
for k,v in aDict.items():
if(v == 'US'):
aDict[( '1+'+k)]=aDict.pop(k)
if(v == 'UK'):
aDict[( '044+'+k)]=aDict.pop(k)
if (v == 'BD'):
aDict[('001+'+k)] =aDict.pop(k)
return aDict
new_user=list(map(add_Country_Code,user))
print(new_user)
This works partially when I run, output below :
[{'1+952-201-3787': 'US'}, {'1+1+1+952-201-5984': 'US'}, {'001+9871299': 'BD'}, {'044+01632 960513': 'UK'}]
Notice the 2nd US number has 2 additional 1s'. What is causing that?How to fix? Thanks a lot.
Issue
You are mutating a dict while iterating it. Don't do this. The Pythonic convention would be:
Make a new_dict = {}
While iterating the input a_dict, assign new items to new_dict.
Return the new_dict
IOW, create new things, rather than change old things - likely the source of your woes.
Some notes
Use lowercase with underscores when defining variable names (see PEP 8).
Lookup values rather than change the input dict, e.g. a_dict[k] vs. a_dict.pop(k)
Indent the correct number of spaces (see PEP 8)

Format numeric values in Filemaker 12 List() result

I'm using List() to retrieve a numeric field which I subsequently display on a report view via a merge variable inside a text field. The data being displayed is a list of employees who worked on a particular job on a particular day, and the number of hours they worked under various classifications (normal, overtime, non-billable, non-billable overtime, et al). The hours are all calculated fields pulled from another table, but they need to be stored numerically.
Each column has its own text field:
| <<$$Name>> | <<$$normalHours>> | <<$$otHours>> | ...
Giving output such as:
Jim Jones 8 2
Ralph Ryder 4.25 0
Foo McBar 10 2.5
The field height needs to be dynamic because there could be anywhere from 1 to 10 or so employees displayed.
The issue is that I would like to always display the hours field with two decimal places:
Jim Jones 8.00 2.00
Ralph Ryder 4.25 0.00
Foo McBar 10.00 2.50
This is normally trivial via Inspector -> Data for a single-value field, and perhaps it still is trivial -- but I'm just not seeing it.
I've tried using SetPrecision(hours ; 2) when populating the field, and also (though I didn't think it would actually work) when creating my list variable:
$$normalHours = SetPrecision( List( laborTable::normalHours ) ; 2 )
In both cases I still see plain integer output for whole numbers and no trailing zeroes in any case.
Please let me know if I can provide any further information that might help.
A few things you can try:
Auto-enter calculation replacing existing value
You could change your normalHours field to be an auto-enter calculation, uncheck 'do not replace existing value', and set the calculation to the following:
Let ( [
whole = Int ( Self ) ;
remainder = Abs ( Self ) - Abs ( whole )
] ;
Case ( remainder = 0 ;
whole & ".00" ;
Self )
)
This will append a ".00" to any whole numbers in your field. This should then come through your List() function later.
New calculation field
Alternately, if you don't want to automatically modify the existing number, you could make a new calculation field with a very similar calculation:
Let ( [
whole = Int ( normalHours ) ;
remainder = Abs ( normalHours ) - Abs ( whole )
] ;
Case ( remainder = 0 ;
whole & ".00" ;
normalHours )
)
And then you would use that calculation field in the List function, instead of your normalHours field.
For more complicated field formatting, you could also use a custom function like this: http://www.briandunning.com/cf/945
Can you replace this with a portal, perhaps?
If not, then try to set formatting on the merge text field itself. It can have formatting too; only one variant for each data type, but in your case it should be enough.

MDX - distinct count

I was following this article:
http://msdn.microsoft.com/en-us/library/aa902637%28v=sql.80%29.aspx
and my query for distinct count looks like this:
Count(CrossJoin({[Measures].[Submission Count]}, [Submission].[PK Submission].Members), ExcludeEmpty)
it returns always 1 more than it should (for example it returns 27 instead of 26).
In the same article there is this query (which is suppose to solve this problem):
Count(CrossJoin( {[Sales]},
Descendants([Customers].CurrentMember, [Customer Names])),
ExcludeEmpty)
But I can't get it to work. I've tried these two but second one always returns 1 or 0 while the first one doesn't work (error: I have to explicitly define a level):
Count(CrossJoin( {[Measures].[Submission Count]},
Descendants([Submission].CurrentMember, [Submission].[PK Submission])),
ExcludeEmpty)
Count(CrossJoin( {[Measures].[Submission Count]},
Descendants([Submission].[PK Submission].CurrentMember, [Submission].[PK Submission])),
ExcludeEmpty)
Any idea what am I doing wrong?
Thanks!
The reason the first query returns "1 more than it should" is because the [Submission].[PK Submission].Members tuple set also includes the All member.
If you refer to the [PK Submission] level instead of all the members of the [PK Submission] hierarchy, it doesn't include the All member.
So, the following returns what you're expecting:
Count( CrossJoin( { [Measures].[Submission Count] }
, { [Submission].[PK Submission].[PK Submission] })
, ExcludeEmpty)

Resources