I am new to SSAS and I'm having some trouble with a "count of rows" measure.
I'm doing this all with named queries from a MySQL database and have created two logical tables in my DSV. The first table is called "Person" and has a primary key of "Person GUID". The second is called "Role" and has a primary key of "Role GUID" and a foreign key of "Person GUID". This is acting as a dimension table and also has an attribute of "Role Name".
What I want to do is be able to select a role from my dimension table and have this show me the number of people in that role, using a "count of records" measure from the Person table. The problem is, people can hold multiple roles, and the way it is structured in my "Role" table is that there is a separate row for each role that a person might have...in other words, "Person GUID", which is how it is mapped to the measure group, could be duplicated many times.
This is not working in SSAS - It doesn't seem to be giving me an accurate count. It appears to be only considering the role of the first instance of a particular Person GUID.
I know that I must be looking at this the wrong way...any help that anyone could offer would be much appreciated. I understand that I could just do a count of rows on the "Roles" table and then be done with it but because I have other dimensions that I want to correlate with it that are also mapped to the "Person" table, this isn't an acceptable solution for me. (These other dimensions have "Person GUID" as the primary key and thus don't have the same problem)
Sounds like you need to model a many to many dimension relationship between the person fact table and role dimension.
Your current role dimension sounds like it needs to be split out into a new bridge table mapping persons to roles. The other table is a simplified role table joining to the mapping table.
Related
This question already has answers here:
How to implement one-to-one, one-to-many and many-to-many relationships while designing tables?
(4 answers)
Closed 2 months ago.
Imagine I want to create a SQLite database of films, where the columns correspond to: title publication year, genre... How would you do it to store a list of actors in the database? Consider that:
Since the number of actors may vary from film to film, I cannot use one column per actor.
SQLite does not have a data type that corresponds to a list.
I want to use, for example "SELECT filmname FROM table WHERE X". Where X would be something that indicates if an actor is present in the film. I would like to be able to use a single or multiple actors on X
The best thing I though is to use a single string, like "actor1_actor2", and then apply "WHERE actorname LIKE %actor1". But that would allow me to filter films by only one actor.
Thanks!
You create tables movies, actors and a separate bridge table movies_actors for defining your many-to-many relationship (movie<->actor). The simplest form of the bridge table includes two columns, such as movie_id and actor_id, and two foreign keys: movies_actors.movie_id -> movies.id and movies_actors.actor_id -> actors.id.
I would suggest, create a mapping separate table for the actress with a mapping key as Film's primary table. so that you can run all type of query operations on your table structure.
I am developing an application which tracks class attendance of students in a school, in Apex.
I want to create a page with three level cascading select lists, so the teacher can first select the Semester, then the Subject and then the specific Class of that Subject, so the application returns the Students who are enrolled in that Class.
My problem is that these three tables have a many-to-many relationship between them, so I use extra tables with their keys.
Every Semester has many Subjects and a Subject can be taught in many Semesters.
Every Subject has many classes in every Semester.
The students must enroll in a subject every semester and then the teacher can assign them to a class.
The tables look something like this:
create table semester(
id number not null,
name varchar2(20) not null,
primary key(id)
);
create table subject(
id number not null,
subject_name varchar2(50) not null,
primary key(id)
);
create table student(
id number not null,
name varchar2(20),
primary key(id)
);
create table semester_subject(
id number not null,
semester_id number not null,
subject_id number not null,
primary key(id),
foreign key(semester_id) references semester(id),
foreign key(subject_id) references subject(id),
constraint unique sem_sub_uq unique(semester_id, subject_id)
);
create table class(
id number not null,
name number not null,
semester_subject_id number not null,
primary key(id),
foreign key(semester_subject_id) references semester_subject(id)
);
create table class_enrollment(
id number not null,
student_id number not null,
semester_subject_id number not null,
class_id number,
primary_key(id),
foreign key(student_id) references student(id),
foreign key(semester_subject_id) references semester_subject(id),
foreign key(class_id) references class(id)
);
The list of value for the Semester select list looks like this:
select name, id
from semester
order by 1;
The the subject select list should include the names of all the Subjects available in the semester selected above, but I can't figure the query or even if it's possible. What I have right now:
select s.name, s.id
from subject s, semester_subject ss
where ss.semester_id = :PX_SEMESTER //value from above select list
and ss.subject_id = s.id;
But you can't have two tables in a LoV and the query is probably wrong anyway...
I didn't even begin to think about what the query for the class would look like.
I appreciate any help or if you can point me in the right direction so I can figure it out myself.
Developing an Apex Input Form Using Item-Parametrized Lists of Values (LOVs)
Your initial schema design looks good. One recommendation once you've developed and tested your solution on a smaller scale, append to the ID (primary key) columns a trigger that can auto-populate its values through a sequence. You could also skip the trigger and just reference the sequence in your sql insert DML commands. It just makes things simpler. Creating tables in the APEX environment with their built-in wizards offer the opportunity to make an "auto-incrementing" key column.
There is also an additional column added to the SEMESTER table called SORT_KEY. This helps when you are storing string typed values which have logical sorting sequences that aren't exactly alphanumeric in nature.
Setting Up The Test Data Values
Here is the test data I generated to demonstrate the cascading list of values design that will work with the example.
Making Dynamic List of Value Queries
The next step is to make the first three inter-dependent List of Values definitions. As you have discovered, you can reference page parameters in your LOVs which may come from a variety of sources. In this case, the choice selection from our LOVs will be assigned to Apex Page Items.
I also thought only one table could be referenced in a single LOV query. This is incorrect. The page documentation suggests that it is the SQL query syntax that is the limiting factor. The following LOV queries reference more than one table, and they work:
-- SEMESTER LOV Query
-- name: CHOOSE_SEMESTER
select a.name d, a.id r
from semester a
where a.id in (
select b.semester_id
from semester_subject b
where b.subject_id = nvl(:P5_SUBJECT, b.subject_id))
order by a.sort_id
-- SUBJECT LOV Query
-- name: CHOOSE_SUBJECT
select a.subject_name d, a.id r
from subject a
where a.id in (
select b.subject_id
from semester_subject b
where b.semester_id = nvl(:P5_SEMESTER, b.semester_id))
order by 1
-- CLASS LOV Query
-- name: CHOOSE_CLASS
select a.name d, a.id r
from class a, semester_subject b
where a.semester_subject_id = b.id
and b.subject_id = :P5_SUBJECT
and b.semester_id = :P5_SEMESTER
order by 1
Some design notes to consider:
Don't mind the P5_ITEM notation. The page in my sample app happened to be on "page 5" and so the convention goes.
I chose to assign a name for each LOV query as a hint. Don't just embed the query in an item. Add some breathing room for yourself as a developer by making the LOV a portable object that can be referenced elsewhere if needed.
MAKE a named LOV for each query through the SHARED OBJECTS menu option of your application designer.
The extra operator involving the NVL command, as in nvl(:P5_SUBJECT, b.subject_id) for the CHOOSE_SEMESTER LOV is an expression mirrored on the CHOOSE_SUBJECT query as well. If the default value of P5_SUBJECT and P5_SEMESTER are null when entering the page, how does that assist with the handling of the cascading relationships?
The table SEMESTER_SUBJECT represents a key relationship. Why is a LOV for this table not needed?
APEX Application Form Design Using Cascading LOVs
Setting up the a page for testing the schema design and LOV queries requires the creation of three page items:
Each page item should be defined as a SELECT LIST leave all the defaults initially until you understand how the basic design works. Each select list item should be associated with their corresponding LOV, such as:
The key design twist is the Select List made for the CHOOSE_CLASS LOV, which represents a cascading dependency on more than one data source.
We will use the "Cascading Parent" option so that this item will wait until both CHOOSE_SEMESTER and CHOOSE_SUBJECT are selected. It will also refresh if either of the two are changed.
YES! The cascading parent item can consist of multiple page items/elements. They just have to be declared in a comma separated list.
From the online help info, this is a general introduction to how cascading LOVs can be used in APEX designs:
From Oracle Apex Help Docs: A cascading LOV means that the current item's list of values should be refreshed if the value of another item on this page gets changed.
Specify a comma separated list of page items to be used to trigger the refresh. You can then use those page items in the where clause of your "List of Values" SQL statement.
Demonstration of APEX Application Items with Cascading LOVs
These examples are based on the sample data given at the beginning of this solution. The path of the chosen example case is:
SEMESTER: SPRING 2014 + SUBJECT: PHYS ED + Verify Valid Course Options:
Fitness for Life
General Flexibility
Presidential Fitness Challenge
Running for Fun
Volleyball Basics
The choice from above will be assigned to page item P5_CLASS.
Selection Choices for P5_SEMESTER:
Selection Choices for P5_SUBJECT:
Selection Choices for P5_CLASS:
Closing Remarks and Discussion
Some closing thoughts that occurred to me while working with this design project:
About the Primary Keys: The notion of a generic, ID named column for a primary key was a good design choice. While APEX can handle composite business keys, it gets clumsy and difficult to work around.
One thing that made the schema design challenging to work with was that the notion of "id" transformed in the other tables that referenced it. (Such as the ID column in the SEMESTER table became SEMESTER_ID in the SEMESTER_SUBJECT table. Just keep an eye on these name changes with larger queries. At times I actually lost track exactly what ID I was working with.
A Word for Sanity: In the likely event you decide to assign ID values through a database sequence object, the default is usually to begin at one. If you have several different tables in your schema with the same column name: ID and some associating tables such as CLASS_ENROLLMENT which connects the values of one primary key ID and three additional foreign key ID's, it may get difficult to discern where the data values are coming from.
Consider offsetting your sequences or arbitrarily choosing different increments and starting values. If you're mainly pushing ID's around in your queries, if two different ID sets are separated by two or three orders of magnitude, it will be easy to know if you've pulled the right data values.
Are There MORE Cascading Relationships? If a "parent" item relationship indicates a dependency that makes a page item LOV wait or change depending on the value of another, could there be another cascading relationship to define? In the case of CHOOSE_SEMESTER and CHOOSE_SUBJECT is it possible? Is it necessary?
I was able to figure out how to make these two items hold an optional cascading dependency, but it required setting up another outside page item reference. (If it isn't optional, you get stuck in a closed loop as soon as one of the two values changes.) Fancy, but not really necessary to solve the problem at hand.
What's Left to Do? I left out some additional tasks for you to continue with, such as managing the DML into the ENROLLMENT table after selecting a valid STUDENT.
Overall, you've got a workable schema design. There is a way to represent the data relationships through an APEX application design pattern. Happy coding, it looks like a challenging project!
I'm creating an asp.net site that used linq to sql to create, edit and delete cars and race results. Each car has it's own number which has been set as the primary key. Each result has a result number, and there is a many-to-one relationship between the results and cars.
To create a new car object I use the Car DataContext, which automatically updates the database as requires using the DataContext.SubmitChanges() function. However it won't update the primary key, instead choosing a new one by incrementing the largest current value.
Since each car's number is important, is there any way to choose the primary key value using this method? Or should I make the car ID separate and use a separate piece of code to make sure the ID is unique?
As you aluded to in your question, keeping the Car number separate from its Id is the way to go. The reason for this is that it is possible that two cars could at some point have the same number, in addition to the fact that the database is choosing its own value for the Id anyway.
Just add another field to your Car table to record its number and you should be good to go.
See Update primary key value using entity framework for more information.
i have two tables
asset employee
assetid-pk empid-pk
empid-fk
now, i have a form to populate the asset table but it cant because of the foreign key constraint..
what to do?
thx
Tk
Foreign keys are created for a good reason - to prevent orphan rows at a minimum. Create the corresponding parent and then use the appropriate value as the foreign key value on the child table.
You should think about this update as a series of SQL statements, not just one statement. You'll process the statements in order of dependency, see example.
Asset
PK AssetID
AssetName
FK EmployeeID
etc...
Employee
PK EmployeeID
EmployeeName
etc...
If you want to "add" a new asset, you'll first need to know which employee it will be assigned to. If it will be assigned to a new employee, you'll need to add them first.
Here is an example of adding a asset named 'BOOK' for a new employee named 'Zach'.
DECLARE #EmployeeFK AS INT;
INSERT (EmployeeName) VALUES ('Zach') INTO EMPLOYEE;
SELECT #EmployeeFK = ##IDENTITY;
INSERT (AssetName, EmployeeID) VALUES ('BOOK',#EmployeeFK) INTO ASSET;
The important thing to notice above, is that we grab the new identity (aka: EmployeeID) assigned to 'Zach', so we can use it when we add the new asset.
If I understand you correctly, are you trying to build the data graph locally before persisting to the data? That is, create the parent and child records within the application and persist it all at once?
There are a couple approaches to this. One approach people take is to use GUIDs as the unique identifiers for the data. That way you don't need to get the next ID from the database, you can just create the graph locally and persist the whole thing. There's been a debate on this approach between software and database for a long time, because while it makes a lot of sense in many ways (hit the database less often, maintain relationships before persisting, uniquely identify data across systems) it turns out to be a significant resource hit on the database.
Another approach is to use an ORM that will handle the persistence mapping for you. Something like NHibernate, for example. You would create your parent object and the child objects would just be properties on that. They wouldn't have any concept of foreign keys and IDs and such, they'd just be objects in code related by being set as properties on each other (such as a "blog post" object with a generic collection of "comment" objects, etc.). This graph would be handed off to the ORM which would use its knowledge of the mapping between the objects and the persistence to send it off to the database in the correct order, perhaps giving back the same object but with ID numbers populated.
Or is this not what you're asking? It's a little unclear, to be honest.
I've read about primary, unique, clustered indexes etc. But I need to understand it via an example.
The image below is the auto-generated aspnet_Users table captured from SQL Server Web Admin Panel.
Auto-generated ASP.NET Users Table http://eggshelf.com/capture.jpg
Taking this as a model; I will create a custom table called Companies and let's say the fields are: ID, Name, ShortName, Address, City, Country.. No values can be duplicate for ID, Name and ShortName fields.
What is your approach on creating indexes for this table? Which should be clustered or non-clustered? Are indexes below logical to you?
Index Columns Primary Unique Clustered ign.Dup.Keys Unique Key
------------------------------------------------------------------------------------------
PK_ID ID True True False False False
Comp_Index Name,ShortName False True True False False
regards..
Indexes are not about table structure, but about access patterns.
You need to see how you query the data in the table and create your indexes accordingly.
The rule of thumb is to consider defining indexes on fields that are commonly used in the WHERE clause.
See this blog post on the subject.
Update
You can only define a single clustered index on a table. This is normally done on the identity field of the table, as you have in your example.
Other indexes will be non-clustered.
In regards to the other (non-clustered) index - if you intend on only having queries that contain both fields in the WHERE clause and the ORDER BY will have a primary sort on Name (as opposed to a primary sort on ShortName). The reason for that is that this is how the index will be stored - first on Name, then on ShortName.
If however, you will use ShortName as primary sort or without Name in the WHERE clause, you are better off with two indexes, one for each.
Go and get a quick overall understanding of SQL Server Indexes by reading Brad's Sure Guide to Indexes
Typically, having not performed any query analysis your starting point will be:
The Primary Key column can make a good candidate for the Clustered Index (often dependant on data type used and key width).
You should create Non-Clustered indexes on Foreign Key Columns.
You should create Non-Clustered indexes on SARG columns from your queries.
Then take a look at these generic index tips.
Oded is right - indices (Clustered and non) are all about performance and needs intimate knowledge about the types of queries.
e.g. If both ShortName and Name are both queried independently, you might want to have separate Non Clustered indexes for ShortName and Name.
If you need to enforce uniqueness, use UNIQUE INDEX (or add UNIQUE CONSTRAINTs to ShortName and Name). ID is already unique as it is the PK.
You can also change the Clustered Index (from its default of ID) if you know more about how data from your companies table will be fetched (e.g. Cluster on City if it is common practice to fetch all Companies in a City at once etc)