I'm quite new to MDX and I'm having a bit of an issue with the aggregation of one of my measures.
In my DSV I have an "Events" table. We track the agents that run these events, and since multiple agents can be involved in running a single event, I have split this out into a separate table of "Agent" with a bridging table in the middle:
http://imgur.com/uAy3moC
I want to track what is called "Coverage", which is the number of Events held in a particular week and also each agent who ran the event. So if there were 3 events held one week, and one of these events were run by two agents, that would be a coverage of 4.
When I go to analyse the cube, dragging on Week Commencing and my count of Events, I note that it isn't right - It only considers individual events and not the number of agents. Dragging on Agents solves this but I still want to see an overall figure without having to drag on Agents.
So I created a calculated member like so:
CREATE MEMBER CURRENTCUBE.[Measures].[Visit Coverage]
AS
IIF([Agents].[Agent].currentmember.parent IS NULL,
SUM([Agents].[Agent].[Agent], [Measures].[Events Count]),
[Measures].[Events Count]);
So basically, if all agents are selected (parent is null), sum up all of the events count for each agent, otherwise just give me the events for each individual agent if I'm analysing by agent. This works great...and also works if I want to filter by one particular agent, but then falls over if I try to filter by more than one (but less than all) agents, giving me a null value.
I'm completely stumped on how to solve this one, could anyone help me out?
Chris
Your table design covers the requirement to count the number of events, avoiding a double-counting of agents via the many-to-many bridge table between the main fact table and the agent dimension table. If you want to have a measure that does not avoid double-counting, then its fact table should directly link the dimension tables.
Hence, I would create a view or named query that has foreign keys to your three dimension tables, and use this as the base of a new measure group in addition to the existing ones. This view or named query could just be built as a join from the main fact table and the bridge table. Then add a count as the coverage measure to this measure group.
Related
We have a Tabular model with several Fact tables and several Dim tables.
We would like to manages roles so that specific roles will not be able to see members of a certain attribute within a dimension.
So in an HR cube with a "Work Hour" measure - i would like to block a specific role from seeing the "Employee Name" attribute but still show the sum of "Work Hours" to the total employee.
While using multidimensional, i simply used an MDX expression which filters on the "All" member of the dimension thus showing the total but not the members of an attribute.
Don't know how to do so in Tabular Model.
Did someone encounter a similar request?
Thank you!
Yes, Tabular models don't give you the option of disabling "visual totals". So this isn't easy to do. However if you get creative you can do it. If you remember that calculated columns are calculated at processing time without security then you can store the rollups you need ahead of time. Store those rollups somewhere users can read them from even with security in effect. In this case you may need to put the rollups in a separate table, separate from the employees since all rows in that table will be hidden. Here is a full write up:
http://cathydumas.com/2012/05/19/row-security-and-hierarchiespart-1/
However in your case since you want to hide all Employee table rows that will cause all related fact table rows to disappear due to security. So here is what I would suggest. First, disable the relationship to the Employee table. Second, pattern your measures after this pattern:
Work Hours := IF(
COUNTROWS(Employee)>0,
CALCULATE(
SUM(FactHours[Work Hours]),
USERELATIONSHIP(FactHours[EmployeeKey], Employee[EmployeeKey])
),
SUM(FactHours[Work Hours])
)
The logic here is that if your user can't see any employees then don't enable that relationship. If your user can see employees, then enable the relationship.
I have a cube with 3 fact tables and 20 + dimensions that relate easily to all 3 fact tables and everything works fine except for the fact that one of the dimensions (Warehouse) is only related to 2 of the 3 fact tables. My problem I guess is a display issue. When the user is viewing measures from all 3 fact tables then drags over the Warehouse dimension, it simply repeats the grand total of the measure in the 3rd fact table for every possible value of Warehouse. This certainly makes sense to me as there is no relationship set up and it's conceptually behaving almost like a cross-join. Nonetheless, it's confusing to users and I'd like to not have the grand total duplicated for each dimension member in Warehouse. I was thinking one solution was to create a dummy warehouse called "Not Applicable" and then relate every row in the 3rd fact table to that dimension member. I was hoping there's just a setting in SSAS where I could control this behavior so I didn't have to create any new warehouse values. Is there a standard way to handle non-related dimensions with multiple fact tables? Thanks in advance.
You can use the "IgnoreUnrelatedDimensions" property of the measure group not related to Warehouse: set it from the default value true to false. Then, measure values for this measure group will only be shown for the "All" members from the warehouse dimension, and the cells will be null (empty) for non-All members of this dimension.
This is a global setting per measure group, you cannot configure it individually per dimension and measure group. But for your purpose, this should be fine.
Please see link to FileMaker Pro 12 database I've created to illustrate my problem:
https://dl.dropboxusercontent.com/u/24821795/Example.fmp12
I want to count the number of times an Activity has been assigned to a Staff member, but there are a couple of things making it tricky (not impossible, I hope):
When the user performs a Find, the count should update to only include the found records.
The user can add to the list of activities.
In the example provided, SelfJoinCount and Activities::Count are not what I want - they both count Activity (e.g. Archery has been assigned to two staff members), but do not meet criteria 1. above.
Try performing a Find of Gender = M
The values of ReviewedCount (a summary field, counting Reviewed) change to 3, which is what I want.
The values of SelfJoinCount and Activities::Count do not change. In this case, I want them to change to 1 (i.e. One record with Ballooning, one record with Bird watching and one record with Archery in the found set).
I could create a calculation field with a 1 in it if the activity occurs and then a summary field counting that 1 for every single activity in the database, BUT this won't work because of criteria 2. above (also, there are a lot of activities).
Any ideas?
Ok, several problems you have here.
First, you need key values for your tables. This can easily be accomplished by creating a number field in each table. In the options, select auto-enter serial number, validation unique, not empty.
Now, you need a 3rd table for the join. This table will have the foreign key value for the Staff member as well as the foreign key for the activity.
You will want to have your Staff layout in form view, add a portal into the join table with they foreign key field for the activity. Create a popup or drop down list for activities (hint: if you want the name of the activity to show in the layout rather than its key, use a popup.) it needs to have they key value and display second field, all values, show only value from second field.
This will allow you to have a many to many relationship between the tables so that a single staff member can have many activities and an activity can have many staff members.
Now, if you want a count of each activity, you could of course create calculation fields in the staff table to count instances of each activity type, but I find that cumbersome and time consuming as well as requiring you to create TO's for each activity. What you really want to use is an ExecuteSQL() function. Some thing like this:
ExecuteSQL("
SELECT COUNT(J.FK_ActivityID)
FROM JoinTable J
WHERE J.FK_StaffID =?
Group by J.FK_ActivityID";"";"";Staff::PK_StaffID)
You can tweak that ExecuteSQL to include a specific activity, or leave it as it is an include them all. Up to you how you do it.
If it wasn't 7am and having had no sleep, I would mock up the file for you, but I think you would do better testing it and working on it on your own.
I am currently going to be designing an app in vb.net to work with an access back-end database. I have been trying to think of ways to reduce down data redundancy
and I have an example scenario below:
Lets imagine, for an example purpose, I have a customers table and need to highlight all customers in WI and send them a letter. The customers table would
contain all the customers and properties associated with customers (Name, Address, Etc) so we would query for where the state is "WI" in the table. Then we would
take the results of that data, and append it into a table with a "completion" indicator (So from 'CUSTOMERS' to say 'WI_LETTERS' table).
Lets assume some processing needs to be done so when its completed, mark a field in that table as 'complete', then allow the letters to be printed with
a mail merge. (SELECT FROM 'WI_LETTERS' WHERE INDICATOR = COMPLETE).
That item is now completed and done. But lets say, that every odd year (2013) we also send a notice to everyone in the table with a state of "WI". We now query the
customers table when the year is odd and the customer's state is "WI". Then append that data into a table called 'notices' with a completion indicator
and it is marked complete.
This seems to keep the data "task-based" as the data is based solely around the task at hand. However, isn't this considered redundant data? This setup means there
can be one transaction type to many accounts (even multiple times to the same account year after year), but shouldn't it be one account to many transactions?
How is the design of this made better?
You certainly don't want to start creating new tables for each individual task you perform. You may want to create several different tables for different types of tasks if the information you need to track (and hence the columns in those tables) will be quite different between the different types of tasks, but those tables should be used for all tasks of that particular type. You can maintain a field in those tables to identify the individual task to which each record applies (e.g., [campaign_id] for Marketing campaign mailouts, or [mail_batch_id], or similar).
You definitely don't want to start creating new tables like [WI_letters] that are segregated by State (or any client attribute). You already have the customers' State in the [Customers] table so the only customer-related attribute you need in your [Letters] table is the [CustomerID]. If you frequently want to see a list of Letters for Customers in Wisconsin then you can always create a saved Query (often called a View in other database systems) named [WI_Letters] that looks like
SELECT * FROM Letters INNER JOIN Customers ON Customers.CustomerID=Letters.CustomerID
WHERE Customers.State="WI"
I have designed a fact table that stores the facts for a specific date dimension and an action type such as create, update or cancelled. The facts can be create and cancelled only once, but update many times.
myfact
---------------
date_key
location_key
action_type_key
This will allow me to get a count for all the updates done, all the new ones created for a period and specify a specific region through the location dimension.
Now in addition I also have 2 counts for each fact, i.e. Number of People, Number of Buildings. There is no relation between these. And I would like to query on how many of the facts having a specific count, such as how many have 10 building, how many have 9 etc.
What would be the best table design for these. Basically I see the following options, but am open to hear better solutions.
add the counts as reference info in the fact table as people_count and building_count
add a dimension for each of these that stores the valid options, i.e. people dimension that stores a key and a count and building dimension that stores a key and a count. The main fact will have a people_key and a building_key
add one dimension for the count these is used for both people and building counts, i.e. count dimension that stores a key and a generic count. The main fact will have a people_count_key and a building_count_key
First your counts are essentially "dimensions" in the purest sense (you can think of dimensions as a way to group records for reporting purposes). The question though is whether dimensional modeling is what you want to do. I think you are better off as seeing this as something of an implicit dimension than you are to add dimension tables. What this means essentially is that dimension tables add nothing and they create corner cases of errors I just don't think are very helpful unless you need to track a bunch of information related to numbers.
If it were me I would just add the counts to the fact table, not to other tables.