I am sorry if this is a bit broad but I've been working on a structure for a couple of days and I can't seem to figure this out the cleanest and most efficient way to do this. I could share the tables that I've created for now but I really think it's not close to how a proper diagram should be.
Let me describe my problem a bit:
I have Stores, Countries, Districts, Categories.
Each store could belong to different Countries/Districts enabling Store Branch manipulation.
Of course a store could belong to multiple Categories too, for example Store X could be under both Food and Beverages and Night Clubs.
A Country will have multiple Districts and Stores, and a Store could have many Countries and Districts.
I am writing my application using C# and I don't have problems creating data-layer objects and classes. But I need the proper MSSQL structure to manipulate and filter down data based on given criteria.
The most important criteria would be: Going through Countries as a first step, then locating Stores within that Country as a global view, then it's important to sort Stores based on Districts and/or Categories within that Country.
Please let me know if you need me to share what I have for now, but since I'm on Stack Overflow asking this question you can guess that I'm doing this the wrong way.
Anyway, if you could shed some light on this issue and explain how things should be done properly I would highly appreciate it.
Thanks in advance.
Whenever you have many-to-many relationships (e.g. one district may contain many stores; one store may be contained by many districts), you are going to need to use cross-reference tables between those entities.
I'm assuming that a particular district may only be contained by one single country. Here is how I would model out your schenario:
countries(country_id [PK], name, ...)
districts(district_id [PK], country_id [FK], name, ...)
districts_has_stores(district_id [PK], store_id [PK])
stores(store_id [PK], name, ...)
categories_has_stores(category_id [PK], store_id [PK])
categories(category_id [PK], name, ...)
In ER:
districts_has_stores and categories_has_stores are the cross-reference tables representing the many-to-many relationships between your entities.
Based off of this model, you can retrieve all stores within a particular country, and order the stores by district name using the following SQL:
SELECT
c.*
FROM
districts a
INNER JOIN
districts_has_stores b ON a.district_id = b.district_id
INNER JOIN
stores c ON b.store_id = c.store_id
WHERE
a.country_id = <country_id here>
ORDER BY
a.name
Retrieving the count of stores in each country:
SELECT
a.country_id,
COUNT(*) AS store_count
FROM
districts a
INNER JOIN
districts_has_stores b ON a.district_id = b.district_id
GROUP BY
a.country_id
Edit: As per your comment to this answer, here's an example of how you can retrieve all stores that have a category_id of 1:
SELECT
b.*
FROM
categories_has_stores a
INNER JOIN
stores b ON a.store_id = b.store_id
WHERE
a.category_id = 1
Retrieving all stores in a particular category_id (1) and filtering the result to only include those stores within either districts 4 or 5.
SELECT DISTINCT
b.*
FROM
categories_has_stores a
INNER JOIN
stores b ON a.store_id = b.store_id
INNER JOIN
districts_has_stores c ON b.store_id = c.store_id
WHERE
a.store_id = 1 AND
c.district_id IN (4,5)
It's very easy, you have StoryCategory to solve the "many stores can have many categories" problem. The District and Country tables allow you to store the location of your store.
I advise you to look at the following documentation to expand your database design knowledge:
Many To Many
10 useful articles
I think below should work for you.
Countries
=========
CountryId, CountryName
Districts
=========
DistrictId, CountryId, DistrictName
Stores
=========
StoreId, DistrictId, Storename
Categories
=========
CategoryId, Categoryname
StoreCategories
=========
Storecategoryid, StoreId, CategoryId
You would have a country table with an identity column. Each store can "be-a" Category, you'd have to have an association table which is a child table of the store table which would have a store ID and the ID from the Category table. Each store would belong to a country so your store table would store the ID of the country from the Country table. Similar to the Category, your District table would have a child table which stores the ID of the District and of the Country (since each district can have multiple countries)
Store Table
ID INT IDENTITY PK
Category FK
Country FK (where it actually lives, a 1 to 1)
District FK
Category Table
ID INT IDENTITY PK
StoreCategory Table
StoreID FK
CategoryID FK
Country Table
ID INT IDENTITY PK
District Table
ID INT IDENTITY PK
DistrictCountry Table
DistrictID FK
CountryID FK
Related
I am looking to select data from multiple tables and insert into respective text boxes. I can have one table that hold all the data, but as I want to apply normalization to the data sets, I will have to split the data.
I already know that I can use :
SELECT *
FROM users
WHERE Username = UserNametxt.Text.Trim()
and then addWithValue etc.
How would I do this using a PK from one table linked to other tables as a FK?
Table users:
id (pk)
email
password
last_login
Table address:
id (fk to users.id)
houseNumber
StreetName
City
Table postcode:
id (fk to users.id)
PostCode
The above is a rough sample of what the data tables will be.
First of all, you should change the structure of your tables. In order to properly normalize DB, tables address and postcode should have their own id (PK), which does not depend on data from other tables.
If you leave it that way, you won't get rid of data duplication (which is one of the main reasons to normalize DB)
So it would look like that:
Table addresses:
id (PK)
userId (FK)
houseNumber
streetName
city
Table postcodes:
id (PK)
userId (FK)
postCode
And then you need to get information. You need to use JOIN to somehow connect tables and get information you need
SELECT * FROM users
LEFT JOIN addresses ON adresses.UserId=users.Id
LEFT JOIN postcodes ON postcodes.UserId=users.Id
WHERE ...
Sorry if the title was confusing.
Lets say I have a model called Employee. Employee has a column called Departments. This allows them to view the calendar for that department. But some Employees should be able to view the calendar for multiple departments, and it is different for every employee.
Because there are many different departments, I do not want to have the Employee table filled with a ton of new columns for each department.
I saw something about linking (not sure if that is the right word) two tables. So I made a second model/table called AdditionalDepartments that has the AdditionalDepartmentsId, EmployeeId, and Department.
Say Joe was part of department A but can also view B and C. This is what employee looks like.
EmployeeId | name | Department
-------------------------------
1 | Joe | IT
and the AdditionalDepartments would look like...
AdditionalDepartmentsId | EmployeeId | Department
--------------------------------------------------
1 | 1 | HR
2 | 1 | Sales
How would I go about combining these? Or is there a better way to store additional department information rather than two tables?
I ask because in my view, when they create or edit an employee, they use the employee database, but I want to be able to set additional departments on these views. The problem with that is you can only use one model per view so I am having difficulties.
Note: I cannot drop the Department from Employee because it is used for a lot more than what the AdditionalDepartments would be used for.
Change your first table column to something like OfficialDepartment. In your second table, drop the 'Additional' and just leave it as Departments. Add 'IT' to this table for 'Joe' as well. Then output the SQL using the statement below into a List<Departments> into your model and use as needed.
select A.Departments as [Departments]
from Employees E
join Departments D on E.EmployeeId = D.EmployeeId
where E.EmployeeId = <empId>
You would want the Employee model to have an IEnumerable<Department> that contains all the Departments that employee is a part of.
On a somewhat unrelated note, if you have the ability to change the table schema at all, you could just drop the Department column in the first table, and make the second table just be a list of departments associated with employees based on the employeeID columns (they would have a foreign key relationship).
Sorry if I misunderstood your question, but unless you are taking one database to be a single model, this should do the trick for you.
Im making an ordering system where there is a product,supplier and order table. What I'm trying to do is when you order, it can have multiple product and one supplier. Example us OrderID 001 it can have 3 products from product table and 1 supplier from supplier table. How can I do this?
Sorry for asking too much but I don't have a code yet for this part of the system as I don't know where to begin. Thank you.
Create an Orders Table.
Add all ordered products to the order Table.
In the table the three products would all have the same order_id, but a different or (in case someone bought two of the same) same product. You will also need to track the amount they purchase with each row, in case the amount changes.
Select Sum(purchase_amount) from orders where order_id = "YOUR_ORDER_ID"
Select * from orders where order_id = "YOUR_ORDER_ID"
...3 rows show up
You may want to have an order_summary table as well that contains the total amount, etc.
I'm trying to understand how can I get what I need in one query, I describe the situation:
Tables in my DB :
User(ID, Name, DateJoin,) ---- ID is PK
Profile(ID, Name, DateCreated) --- ID is PK
UserProfile(userID, profileID) -- userID & profileID are both PK and FK.
*clarification : each user can have multiply profiles and each profile can be assigned to many users.
Now I have two classes in my application:
AppUser:
ID
Name
DateJoin
List<AppProfile> (List of profiles)
AppProfile:
ID
Name
DateCreated
Now I want in one query to the DB to get the data I need in order to return a :
List<AppUser>, list of AppUser with in each AppUser I have a list of AppProfile that the specific AppUser have.
Update:
Ben answer is what I was looking for but there is one problem in his solution:
Its only returning user that have profiles, users without profiles doesn't return.
so for example I have 2 users, Jones with 2 profiles and Jim with none i get:
Date-Table:
Row[0] : User Name : "Jones", Profile Name: "one".
Row[1] : User Name : "Jones", Profile Name: "two".
There is no mention of Jim ( the other user that no profile associate with him.
There is any way to fix that problem ?
The SQL for this is fairly straightforward, you just join all the tables. You will of course get as many records as their are combinations of users and profiles so you will have to iterate over the result set and populate your classes accordingly.
SELECT *
FROM User u
LEFT OUTER JOIN UserProfile up on u.ID = up.UserId
LEFT OUTER JOIN Profile p on p.Id = up.ProfileId
This would be neater with something like Entity Framework. Using that you could just create a many to many relationship and EF would do all the heavy lifting for you.
UPDATE:
As per your comment I have updated the query to always return all users, even if they have no profiles. UserProfile and Profile fields for these users will contain NULL.
Hi I am new to databases in general, so forgive my noob question below, but I really do need help.
I have designed a database with 4 tables. I have created an application in C# which will store some values in these 4 tables during the course of the application running. However, this is all working fine when there is only one user of the application, but if more that one user is going to use the same application running in an ASP.NET page, then they will be accessing and altering the data in the 4 tables, and problems will soon arise.
My question is, how do I prevent this from happening? I want each user to have their own unique username and then use that to differentiate them in the tables but my knowledge of databases is limited to know how to achieve this. Please help?
Supposing you have the following table today:
FavoriteFood
—————————————
FoodId
FoodName
And it lists all of your favorite foods. But then you decide you'll let me use your database to store my favorite foods too. Since you don't care about my favorite foods, and I don't care about yours, you need a way of keeping them separate. First, you'll create a User table:
User
—————————
UserId
UserName
FirstName
LastName
Then, you need to relate the User table to the FavoriteFood table. One way of doing this would be to add a Foreign Key to the FavoriteFood table. Give it a new field called UserId:
FavoriteFood
—————————————
FoodId
UserId
FoodName
Then you can get just the food for a single user by adding a WHERE clause to your SQL code:
SELECT FoodName
FROM FavoriteFood
WHERE UserId = #UserId
That could be ok, but I'm not satisfied with it. This database is not normalized! Suppose, you later want to store calorie information about your foods. You add a field called calories to your FavoriteFoods table. As you are populating that field with data, you notice that you are putting in the same data multiple times. All of your users like bananas, so you have as many entries in your table for bananas as you have users. You have to enter the exact same calorie information over and over again. Instead, you should have all the information for a food in the table just once, and use a completely separate table to map food to users:
Food
—————————
FoodId
FoodName
Calories
FavoriteFood
—————————————
FoodId
UserId
Use a join to get the favorite food for a user:
SELECT f.FoodName
,f.Caloires
FROM Food f
JOIN FavoriteFood a ON a.FoodId = f.FoodId
WHERE a.UserId = #UserId