Some issues to make mondrian work with a parent-child hierarchy.
My table structure is as follows (simplified, as the Category table is actually a MPTT):
RESPONSE QUESTION CATEGORY
-------------- ------------------- ----------
id ¡---> identifier (String) ¡---> id <---¡
question_id ___| category_id _____| parent_id _|
value (Measure) title name_en
My closure table is a simple setup: child_id, parent_id, distance (with the primary key being the tuple (child_id, parent_id) ).
My cube's schema is as follows:
<Cube cache="true"
defaultMeasure="Value" enabled="true" name="mycube">
<Table name="response" schema="public"/>
<Dimension foreignKey="question_id" name="Category">
<Hierarchy allMemberName="All Categories" hasAll="true"
primaryKey="identifier" primaryKeyTable="question">
<Join leftKey="category_id" rightKey="id">
<Table name="question"/>
<Table name="category"/>
</Join>
<!-- works fine with the category itself: <Level column="name" type="String" name="Category Name" table="category" uniqueMembers="true"/> -->
<Level column="id" name="Category ID"
nameColumn="name_en" nullParentValue="NULL"
parentColumn="parent_id" table="category"
type="Numeric" uniqueMembers="true">
<!-- type="Numeric" ordinalColumn="lft" parentColumn="parent_id" nullParentValue="NULL" -->
<Closure childColumn="child_id" parentColumn="parent_id">
<Table name="category_closure"/>
</Closure>
</Level>
</Hierarchy>
</Dimension>
<Measure aggregator="avg" caption="Value"
column="actual_value" formatString="#,###.00" name="Value"/>
</Cube>
Now, based on the mondrian FoodMart test pages, I have set up a simple jsp pages for my cube, which I want to use as a starting point for my tests. It has the following MDX:
select {[Measures].[Value]} ON COLUMNS,
{( [Category] )} ON ROWS
from [mycube]
The result it shows at first is "All Categories". When I try to drill down or hierarchize in the Categories, it returns nothing but [All Categories]. I have tried also with Descendants() to no avail.
Equally, when I try to list the members of Categories, it returns nothing.
I see that in the background it runs a query as follows to start the drilling down:
05/12/13 23:53:10,967 postgres: [3-1] LOG: execute : select
"category"."id" as "c0", "category"."name_en" as "c1" from "question"
as "question", "category" as "category" where "question"."category_id"
= "category"."id" and "category"."parent_id" IS NULL group by "category"."id", "category"."name_en" order by "category"."id" ASC
NULLS LAST
Obviously this query has an empty result because it joins question with root-level categories whilst only the leaves of my tree are attached some Questions.
It also shows that the closure table is not used here.
Any clue on what I can do to fix this?
Thanks ahead
lai
Following a few experiments, I shall conclude that my use case is probably not supported by Mondrian.
Here is the test I did to come to this conclusion:
- ensure I have 3 levels in my tree (level 0->2)
- create a fake question related to a root category (i.e. whose parent_id = NULL)
- create a response attached to this fake question
- at this stage, only level 0 and level 2 Category records have questions and responses related to them
- go ahead with a query
Here is the result I got in the logs:
14:37:09,082 WARN [SqlTupleReader] The level [Category].[Name] makes
use of the 'parentColumn' attribute, but a parent member for key 3 is
missing. This can be due to the usage of the NativizeSet MDX function
with a list of members form a parent-child hierarchy that doesn't
include all parent members in its definition. Using NativizeSet with a
parent-child hierarchy requires the parent members to be included in
the set, or the hierarchy cannot be properly built natively.
"key 3" relates to one of my level-2 records i.e. tree leaves (similar messages show for the other level-2 records).
Conclusion: not supported :-(
Enclosing the "working" schema below:
<Schema name="Foo">
<Cube name="Foo" caption="Cube to report on the Foo quizz dimensions" visible="true" defaultMeasure="Rating" cache="true" enabled="true">
<Table name="response" schema="public">
</Table>
<Dimension type="StandardDimension" visible="true" foreignKey="question_id" highCardinality="false" name="Category">
<Hierarchy name="Category" visible="true" hasAll="false" allMemberName="All Categories" primaryKey="identifier" primaryKeyTable="question">
<Join leftKey="category_id" rightKey="id">
<Table name="question" schema="public">
</Table>
<Table name="category" schema="public">
</Table>
</Join>
<Level name="Name" visible="true" table="category" column="id" nameColumn="name" ordinalColumn="tree_id" parentColumn="parent_id" nullParentValue="NULL" type="String" uniqueMembers="true" levelType="Regular" hideMemberIf="Never">
</Level>
</Hierarchy>
</Dimension>
<Measure name="Ratings" column="actual_value" formatString="#,###.00" aggregator="avg" caption="Ratings">
</Measure>
</Cube>
</Schema>
Related
I have a source schema as follows:
Users
Id
Name
Department
and destination schema as follows:
Employee
Name
Number
number_type(attribute)
I need to do the following mapping
Name ---> Name
Id ---> Number (number_type = "Id")
Department_no --> Number (number_type = "dept")
I need to map both Id and department number i.e. 2 elements to 1 element i.e. Number in dest schema but for both attribute value should be different.
Input
<Users>
<Id>123</Id>
<Name>abc</Name>
<Department_no>456</Department_no>
</Users>
Output:
<Employee>
<Name>abc</Name>
<Number number_type = "Id">123</Number>
<Number number_type = "dept">456</Number>
</Employee>
How can I achieve in BizTalk or what could be the inline XSLT for the same?
You nearly have it
Name ---> Name
Id ---> Number
Department --> Number
Then also link both Id & Department to a looping functoid that goes to Number
Plus to do the attributes there are some things you can try such as
Id ---> number_type
Department --> number_type
But click on the links select Copy Name instead of the Copy Text value.
From an input
<ns0:Root xmlns:ns0="http://Scratch.SO55049939Input">
<Users>
<Id>Id_0</Id>
<Name>Name_0</Name>
<Department>Department_0</Department>
</Users>
</ns0:Root>
You will get output
<ns0:Root xmlns:ns0="http://Scratch.SO55049939output">
<Employee>
<Name>Name_0</Name>
<Number number_type="Id">Id_0</Number>
<Number number_type="Department">Department_0</Number>
</Employee>
</ns0:Root>
Use version:4.5.0
db/system/config/db/test/collection.xconf The code is as follows:
<range>
<create qname="item">
<condition attribute="name" value="number"/>
<field name="number" match="#value" type="xs:decimal"/>
</create>
<create qname="item">
<condition attribute="name" value="acreage"/>
<field name="acreage" match="#value" type="xs:decimal"/>
</create>
<create qname="item">
<condition attribute="name" value="radii"/>
<field name="radii" match="#value" type="xs:decimal"/>
</create>
<create qname="item">
<condition attribute="name" value="diameter"/>
<field name="diameter" match="#value" type="xs:decimal"/>
</create>
</range>
Browse Indexes
db/test The code of an XML file is as follows:
<root>
<item name="number" value="4"/>
<item name="acreage" value="5"/>
<item name="radii" value="6"/>
<item name="diameter" value="7"/> </root>
Query statement:
//item[#name='radii'][#value>5.0]
Query Profiling
No result
In theory, the XML file can be found, but the result can not be found for what? Can you help me? Thank you!
Based on the documentation for eXist's Conditional Combined Indexes feature you are trying to use here, it appears to me that this feature only support string comparisons (with an optional "numeric" mode). See https://exist-db.org/exist/apps/doc/newrangeindex#D3.21.18. In other words, your #type="xs:decimal" is not resulting in your attributes' values being cast to xs:decimal; effectively, instead, they are being indexed as xs:string.
Thus, for your query to work with the given data, change the predicate to [#value gt "5"].
Or, to force numeric comparisons, add numeric="yes" to the <field> element in your index definitions, and then change your predicate to [#value gt "5.0"].
For my model with the following fields:
name = fields.Char()
date = fields.Date()
value1 = fields.Float()
value2 = fields.Float()
I am trying to show multiple lines in the same graph this way:
<graph string="Results" type="line">
<field name="date" type="row" interval="day"/>
<field name="value1" type="measure" operator="+"/>
<field name="value2" type="measure" operator="+"/>
</graph>
But it shows only one line. Every time I have to select the measure I want to see and deselect the other, while I need to see both at the same time.
The only way I was able to show the two values separately at the same time, is through a bar graph grouped by name field, but it is not what I need (I still had to show only one measure but at least I could achieve to have different colors for each group).
Any ideas?
I did it:
<graph string="Results" type="line">
<field name="date" type="row" interval="day"/>
<field name="name" type="col"/>
<field name="value1" type="measure" operator="+"/>
</graph>
I just need to put all values into value1 and separate them by using name, obtaining different lines with same name
There are three tables -
1) Student - My fact Table (References Addresses with FK ADDRESS_ID
2) Addresses - This table Contains FK COUNTRY_ID references COUNTRY
3) Country - this has a NAME COLUMN which i would display. (PK IDENTIFIER)
I have written this but Not Sure if it is Correct
Basically i want to join Student (FACT TABLE) to COUNTRY
Consosts of Fact --- Def .. then this
<Dimension foreignKey="ADDRESS_ID" name="COUNTRY">
<Hierarchy name="COUNTRY NAME" hasAll="true" primaryKey="IDENTIFIER" primaryKeyTable="ADDRESSES">
<Join leftKey="IDENTIFIER" rightKey="IDENTIFIER">
<Table name="ADDRESSES" >
</Table>
<Table name="COUNTRIES" >
</Table>
</Join>
<Level name="Country Name" visible="true" table="COUNTRIES" column="NAME" nameColumn="NAME" uniqueMembers="false">
</Level>
</Hierarchy>
</Dimension>
You haven't made the join correctly. I'm going to assume your relational schema looks like this:
.-STUDENT-------.
| IDENTIFIER PK | .-ADDRESSES-----.
| ADDRESS_ID FK |----| IDENTIFIER PK | .-COUNTRIES-----.
| COUNTRY_ID FK |----| IDENTIFIER PK |
| NAME |
The JOIN element needs to make a join between the lowest-granularity dimension table ADDRESS and the next level up (COUNTRY). The keys that join these tables are COUNTRY_ID (for ADDRESS) and IDENTIFIER (COUNTRY). leftKey then needs to be set to COUNTRY_ID.
Also, you're using the Level's nameColumn attribute, but this is actually used to set the level's own name, not the member names. I would remove this. In all you'd en up with something looking like this:
<Dimension foreignKey="ADDRESS_ID" name="COUNTRY">
<Hierarchy name="COUNTRY NAME" hasAll="true" primaryKey="IDENTIFIER" primaryKeyTable="ADDRESSES">
<Join leftKey="COUNTRY_ID" rightKey="IDENTIFIER">
<Table name="ADDRESSES" >
</Table>
<Table name="COUNTRIES" >
</Table>
</Join>
<Level name="Country Name" visible="true" table="COUNTRIES" column="NAME">
</Level>
</Hierarchy>
</Dimension>
I am using CF8 and MySQL 5.
I have a form with several date fields (one for each day and the form may have 10+ days of data on it) that the user can select different dates for and they all have different var names within a loop.
The default values for these date fields is null in the DB. I can insert a date into a DATE column in MySQL with no issues and have verified that the data is inserted correctly (using cfqueryparam DATE also).
I have the 'value' of the form datefield set to the variable name and can not get the value to show up.
The date updates to the DB fine every time it is entered, but when the form posts back to itself the date fields are blank (other non-date fields work fine and changes show up).
Then when I submit it with the blank date fields the value is set back to null in the DB (empty string in the form) since the form field does not pull the value from the DB.
The field name (ses#i#Date) shows up correctly (ses1Date, ses2Date, etc...) in the form with the right value when I dump it.
<cfloop from="1" to="#form.days#" index="i"> <cfinput type="datefield" name="ses#i#Date" value="#DateFormat(qGetUWHeader["ses#i#Date"],"yyyy-mm-dd")#" /> ....
Thanks for your time and help.
To reference dynamic column names, you can use array notation. But as I mentioned, you must supply a row number.
#queryName["columnName"][rowNumber]#
If you know the query contains one (1) record, only, you could use the query object's "recordCount" property as the row number. Alternatively, you could hard code the row number "1". (Personally, I dislike hard-coding). But any one of these should work.
<!--- pick ONE option --->
<cfloop from="1" to="#form.days#" index="i">
<!--- syntax option 1 --->
<cfinput type="datefield" name="ses#i#Date" value="#DateFormat(qGetUWHeader['ses#i#Date'][qGetUWHeader.recordCount], 'yyyy-mm-dd')#" />
<!--- syntax option 2 --->
<cfinput type="datefield" name="ses#i#Date" value="#DateFormat(qGetUWHeader['ses'& i &'Date'][qGetUWHeader.recordCount],'yyyy-mm-dd')#" />
<!--- syntax option 3 --->
<cfinput type="datefield" name="ses#i#Date" value="#DateFormat(qGetUWHeader['ses#i#Date'][1], 'yyyy-mm-dd')#" />
</cfloop>
If however, you are looping through multiple records in the qGetUWHeader query, you can use the query object's "currentRow" property as the row number. But based on the field naming convention, I am guessing the query only contains one (1) record.
EDIT:
I forgot about the initial nulls. You could apply a simple if condition, and only call DateFormat() if the query value is a valid date.
<cfloop from="1" to="#form.days#" index="i">
<cfset dateValue = qGetUWHeader["ses#i#Date"][qGetUWHeader.recordCount]>
<!--- if this is a valid date, format the value --->
<cfif IsDate(dateValue)>
<cfset dateValue = dateFormat(dateValue, "yyyy-mm-dd")>
</cfif>
<cfinput type="datefield" name="ses#i#Date" value="#dateValue#" /><hr>
</cfloop>
Another option is to format the dates in your SQL. Then you would not need to use CF's DateFormat() function. Just be aware that the new result would be a string, not a datetime object.
SELECT DATE_FORMAT(ses1Date, '%Y-%m-%d') AS ses1Date, ....
Where is "qGetUWHeader" defined?
When a form is posted, all values will be posted to the form scope. Therefore in order to display a value from a postback, you should reference the form scope unless you're copying the value into 'qGetUWHeader'. Even though the correct date from the form is being stored in the form scope, you're displaying the default value from qGetUWHeader on post back, unless you're doing something there I'm not aware of. Then the next time you post your form, the default value overrides the prior entered value.
<!--- In order to reference FORM values, you must CFPARAM them first to define the default value. --->
<cfparam name="form.days" default="10">
<cfloop from="1" to="#form.days#" index="i">
<cfparam name="form['ses#i#Date']" default="">
</cfloop>
<!--- Display the Form --->
<cfform action="#cgi.SCRIPT_NAME#" method="post">
<cfloop from="1" to="#form.days#" index="i">
<cfset thisFieldName = "ses" & i & "Date">
<cfset thisFieldValue = form["ses#i#Date"]>
<cfoutput>#thisFieldName#</cfoutput> <!--- For Debugging --->
<cfinput type="datefield" name="#thisFieldName#" value="#thisFieldValue#" /><br /><br />
</cfloop>
<input type="submit" name="submit" value="submit" />
</cfform>
<!--- Debug --->
<cfdump var="#form#">