I'm having trouble setting up a report model to create reports with report builder. I guess I'm doing something wrong when configuring the report model, but it might also due to change of primary entity in report builder.
I have 3 tables: Client, Address and Product. The Client has PK ClientNumber. The Address and Product both have a FK relation on ClientNumber. The relation between Client and Address is 1-to-many and also between Client and Product:
Product-(many:1)-Client-(1:many)-Address.
I've created a report model (mostly auto generate) with these 3 tables, for each table I've made an Entity.
Now on the Client Entity , I've got 2 roles, Address and Product. They both have a cardinality of 'OptionalMany', because Client can have multiple Addresses or Products. On both Address and Product I have a Client Role with cardinality 'One', because for each Address or Product, there has to be a Client (tried OptionalOne as well...).
Now I'm trying to create a report in Report Builder (2.0) where I select fields from these three entities. I'd like an overview of Clients with their main address and their products, but I don't seem to be able to create a report with fields from both Address and Products in it. I start by selecting attributes from Client, and as soon as I add Product for example the Primary entity changes as if I'm selecting Products (instead of Clients).
This is a basic example of a problem I'm facing in a much more complex model. I've tried lots of different things for 2 days, but I can't get it to work. Does anyone have an idea how to cope with this?
(Using SSRS 2008)
Edit: in T-SQL this is what i mean:
SELECT *
FROM CLIENT
INNER JOIN ADDRESS ON CLIENT.CLIENT_NUMBER = ADDRESS.CLIENT_NUMBER AND ADDRESS.TYPE = 1 --Main Address
INNER JOIN PRODUCT ON CLIENT.CLIENT_NUMBER = PRODUCT.CLIENT_NUMBER
WHERE CLIENT.CLIENT_NUMBER = 1
My experience dates back to Report Builder 1.0, but MS hasn't changed much in their report model since so it probably still applies.
As you mention, you can define many to many relations in the model, but materializing those relations in one tabular report is not possible. Once you chose one of the entities on the many side (Products), you are left without a way to bring data from the other side (Addresses).
You may have some luck with creating a "junction" table (ClientID-AddressID-ProductID) and hidding it from your users like Bob's SQL Reporting Services Blog suggests.
Ultimately this is a big limitation with MS models and it doesn't seem to improve with their latest incarnation Denali BISM many-to-many
I understand the original post is 4 years old and SSRS report models are becoming irrelevant but one solution is to define the OptionalMany relationships as OptionalOne in the model, essentially fooling the model to allow navigation and appropriate query generation.
Related
I have to build a database with clients and products. The problem is that i should have two types of clients: individuals and companies. I don't get the philosophy for starting the project and some guidelines would be great!
How can i construct the database or the queries to link products to a specific type of client?
Should i make a third clients table and link individuals and companies tables to this table and the products table also linked to this third table or should i have 2 tables for individuals and companies and a flag inside both like "is individual" and "is company"?
When i generate the form to enter a new client i should first select the type of client and based on that a specific form for individuals or company should appear.
Is it a better way to construct that type of client-products database? If i kinda join the two types of clients into just 1 table (an individual have approximatly the same characteristic as a company) it's easy.
Thank you very much!
This question may answer itself, but it is also a question of best practices.
I am designing an application that allows users (comapnies) to create an account. Those users are placed in a table "Shop_table". Now each shop has dynamic data, however the tables would be the same for each shop, like shop_employees, shop_info, shop_data.
Would it be more effective to have a specific table for each shop or would I just link their data by the shop id.
For example:
shop: Dunkins with id:1
shop: Starbucks with id:2
would dunkins have its own dunkins_shop_employees, dunkins_shop_info, dunkins_shop_data tables
and Starbucks have its own starbucks_shop_employees , starbucks_shop_info , starbucks_shop_data
or would i have one table shope_employees, shop_info, shop_data and link by id 1 or 2, etc..
Definitely one table for each entity with a field to identify the company.
If all the companies have the same information there is no need to create tables for each, and if you did your queries will become a nightmare.
Do you really want a load of UNION queries in order to get any aggregate data across companies? You will also have to modify all queries in your DB as soon as another company (and therefore multiple tables) are added.
Define your tables independently, model the entities you want to store and dont think about who they belong to.
You should have only one table ( for each shop_info etc.. )
Creating similar tables is a maintenance nightmare. You will need to create similar foreign keys, similar constraints, similar indexes, etc.
If your concern is privacy, this should be controlled in your application. You application should always add a "WHERE" clause based on who is logged in/ querying.
If you absolutely need to - you can create views which where clause as shop_id. You can give rights to various people on the view only. This would only make sense if you had a big customer who wanted some SQL level query ability.
first of all sorry for my bad english hehehe I need some help, I want to design a database for a website, like a mini Amazon. This database will manage every kind of products (TV, cars, computers, books, videogames, penciles, tables, pants...), but also, each product must have some properties (that will be indexed) for example, if the product is a book, the properties will be something like genre, year, author. If the product is a TV, the properties will be something like size, color, also year. And if the product is a car, the properties will be something like year, color, model, for example. So, this is my idea:
One table to manage departments (like electronics, books...)
One table to manage categories of the departments, this table will be a child of the previous. If the department is electronics, here will be audio, tv and video, games... (each category belongs to one department, the relationship is one department to many categories)
One table to manage the products (each product belongs to one category, the relationship is one category to many products)
One table to manage properties (like year, color, genre, model...)
One table to engage products with properties, this table will be called ProductProperties
Im not sure if this is the best way, the database will be huge, I will develop the database on MySQL. But, I think this is not the best way, this article talks about "Database Abstraction: Aggregation and Generalization" http://cs-exhibitions.uni-klu.ac.at/index.php?id=433, in other words generic objects (I think), but this way is old (70s). In this article http://www.simple-talk.com/sql/database-administration/ten-common-database-design-mistakes/ in the section "One table to hold all domain values" says that this is a wrong way... Im saying all of this because of the table ProductProperties, I dont know if I make this table or if I make especific tables for each kind of products.
Do you have any suggestion? Or do you have a better idea?
Thanks in advance, take care!!!
1.One table to manage departments (like electronics, books...)
2.One table to manage categories of the departments, this table will be a
child of the previous. If the
department is electronics, here will
be audio, tv and video, games... (each
category belongs to one department,
the relationship is one department to
many categories)
Why? One table, categories, forming a hierarchy. More flexible.
3.One table to manage the products (each product belongs to one category,
the relationship is one category to
many products)
Why? Allow m:n here. A product in many categorries.
Im not sure if this is the best way,
the database will be huge
Ah - no. Sorry. Nontrivial, yes. Hugh? No. Just to get you an idea of hugh - I have a db I am adding 1.2 billion rows PER DAY to a specific table. On average. THIS is big. YOu end up with what - 100.000 items? not even worth mentioning.
Pablo89, the description of what you want is very close to what the AdventureWorks database for SQL Server does. There are many examples of using AdventureWorks on the Web from web applicatons to reporting to BI.
Download and install SQL Server Express 2008 R2. Download and install the sample database for the above product. Inspect the database design for AdventureWorks.
Use AdventureWorks as examples in questions you may post.
I use AdventureWorks because I use SQL Server. I do not say it is better than other database products I say this because I know AdventureWorks.
I do not think that some database can work fast with 500,000,000 items. Complete tree of products categories for amazon.com contains 51,000 nodes (amazoncategories.info). Also the data is updated hourly, so saved product information can be incorrect. I think the optimal way is to store categories tree only get the product data at runtime using Amazon's API.
I'm working on a multi-user internet database-driven website with SQL Server 2008 / LinqToSQL / custom-made repositories as the DAL. I have run across a normalization problem which can lead to an inconsistent database state if exploited correctly and I am wondering how to deal with the problem.
The problem: Several different companies have access to my website. They should be able to track their Projects and Clients at my website. Some (but not all) of the projects should be assignable to clients.
This results in the following database schema:
**Companies:**
ID
CompanyName
**Clients:**
ID
CompanyID (not nullable)
FirstName
LastName
**Projects:**
ID
CompanyID (not nullable)
ClientID (nullable)
ProjectName
This leads to the following relationships:
Companies-Clients (1:n)
Companies-Projects (1:n)
Clients-Projects(1:n)
Now, if a user is malicious, he might for example insert a Project with his own CompanyID, but with a ClientID belonging to another user, leaving the database in an inconsistent state.
The problem occurs in a similar fashion all over my database schema, so I'd like to solve this in a generic way if any possible. I had the following two ideas:
Check for database writes that might lead to inconsistencies in the DAL. This would be generic, but requires some additional database queries before an update and create queries are performed, so it will result in less performance.
Create an additional table for the clients-Projects relationship and make sure the relationships created this way are consistent. This also requires some additional select queries, but far less than in the first case. On the other hand it is not generic, so it is easier to miss something in the long run, especially when adding more tables / dependencies to the database.
What would you do? Is there any better solution I missed?
Edit: You might wonder why the Projects table has a CompanyID. This is because I want users to be able to add projects with and without clients. I need to keep track of which company (and therefore which website user) a clientless project belongs to, which is why a project needs a CompanyID.
I'd go with with the latter, having one or more tables that define the allowable relationships between entities.
Note, there's no circularity in the references you have, so the title is misleading.
What you have is the possibility of conflicting data, that's different.
Why do you have "CompanyID" in the project table? The ID of the company involved is implicitly given by the client you link to. You don't need it.
Remove that column and you've removed your problem.
Additionally, what is the purpose of the "name" column in the client table? Can you have a client with one name, differing from the name of the company?
Or is "client" the person at that company?
Edit: Ok with the clarification about projects without companies, I would separate out the references, but you're not going to get rid of the problem you're describing without constraints that prevent multiple references being made.
A simple constraint for your existing tables would be that not both the CompanyID and ClientID fields of the project row could be non-null at the same time.
If you want to use the table like this and avoid the all the new queries just put triggers on the table and when user tries to insert row with wrong data the trigger with stop him.
Best Regards,
Iordan
My first thought would be to create a special client record for each company with name "No client". Then eliminate the CompanyId from the Project table, and if a project has no client, use the "No client" record rather than a "normal" client record. If processing of such no-client's is special, add a flag to the no-client record to explicitly identify it. (I'd hate to rely on the name being "No Client" or something like that -- too fuzzy.)
Then there would be no way to store inconsistent data so the problem would go away.
In the end I implemented a completely generic solution which solves my problem without much runtime overhead and without requiring any changes to the database. I'll describe it here in case someone else has the same problem.
First off, the approach only works because the only table that other tables are referencing through multiple paths is the Companies table. Since this is the case in my database, I only have to check whether all n:1 referenced entities of each entity that is to be created / updated / deleted are referencing the same company (or no company at all).
I am enforcing this by deriving all of my Linq entities from one of the following types:
SingleReferenceEntityBase - The norm. Only checks (via reflection) if there really is only one reference (no matter if transitive or intransitive) to the Companies table. If this is the case, the references to the companies table cannot become inconsistent.
MultiReferenceEntityBase - For special cases such as the Projects table above. Asks all directly referenced entities what company ID they are referencing. Raises an exception if there is an inconsistency. This costs me a few select queries per CRUD operation, but since MultiReferenceEntities are much rarer than SingleReferenceEntities, this is negligible.
Both of these types implement a "CheckReferences" and I am calling it whenever the linq entity is written to the database by partially implementing the OnValidate(System.Data.Linq.ChangeAction action) method which is automatically generated for all Linq entities.
I'm new to reporting svcs and I'm writing a report based on a report model (.smdl) created in VS.NET 2008. I seem to be missing out on the report builder query view's analog to a "left join." Model is very simple:
Three entities:
Cust (custid, custname)
Ord (ordid, custid, orddate, ...)
Charge (chargeid, ordid, chargetype, chargevalue...)
Think of a "charge" as an optional cost (a special charge) associated with an order -- some orders have them, some don't.
Model was auto-generated from views (.dsv) which accurately indicate the relationships between cust and ord, and between ord and charge. I noted that when designing the view relationships there was no kind of option to indicate (for example) that the relationship should be treated as a "left join".
Now I jump to Report Builder 2 (RB2) to design a report based on this model. My goal is to simply list for each order: customer name, order date, charge type, charge value (i.e., order row would repeat if it had more than one charge type). I want ALL orders listed, even if an order doesn't have any charges -- what I would consider a "left join" in the traditional sense.
I use RB2's Query Designer to create the dataset, and merely select (i.e., double-click) the entities I want as fields in the report: custname, orddate, chargetype, chargeval. I then create a simple table in the report based on this dataset.
When running the report, I get only those orders which actually have charges. I was rather hoping to get all orders. Is there a way I can specify that?
Thank you,
Bill Dawson
I got an answer via Sql Server forums:
http://social.msdn.microsoft.com/Forums/en-US/sqlreportingservices/thread/20d4b4fd-dc0b-428e-a5b8-aedf5c53d340
Relevant portion here from Aaron Meyers:
The key here is that all report model queries are centered around a "base entity" and each row at the detail level in your report represents a row in this base entity. You may note that in your model, there is no entity which corresponds to "a charge for an order or just the order if it has no charges". You need to explicitly create this Order-Charge entity in the model, based on a Named Query in the DSV. This named query can just select the keys from the Ord table and the Charge table with a LEFT OUTER JOIN between the two. You then create relationships from these keys to the Ord and Charge tables, and update the model (right-click on Model root node and Autogenerate).
When you start with details from Ord and navigate through the new role to Charge and select additional details, Report Builder will choose the Order-Charge entity as the root/base entity of the report.
We are considering functionality for a future release to allow creating these types of queries directly in Report Builder without requiring the model designer to explicitly create the LEFT OUTER JOIN entity.
I believe the left joins happen based on the order you add fields onto the query designer canvas. As long as you add customer fields, then order fields, then charge fields, you should be right.
You can verify the actual query that was run using SQL Profile which is very handy for debugging these sorts of things.
We can implement LEFT JOIN into the report model between the two entities by using the Cardinality property for an entity's role.
For example, let say we have two entities Customer and Order then.
Customer-->Order role should have Optional One(source)-->Optional Many(Target) {Because 1 customer can have 0 or many Orders}
Order-->Customer role should have Optional Many(source)-->Optional One(Target) {vice versa}