Database design: best approach - database

I'm not a DBA and I don't know what is the best solution. I have two tables,
Custumers Table
CustomerId (primary key, identity)
...
and
Suppliers Table
SupplierId (primary key, identity)
...
and I want to store multiple telephone number and multiple emails. I thought to create two other tables, Emails and Telephones and use those in join with my Custumers and Suppliers, something like
Telephones Table
Id
UserId (reference to SuppliersId or CustomerId)
Value
...
But if I use as key for custumers and suppliers an Identity I'll have for sure problems. I'm thinking to do something like
Telephones Table
Id
SuppliersId
CustumersId
Value
...
But I don't know if is a good design. Any advice?
Thank you

One idea:
Entity (ID (PK), {common fields})
Customer (ID (PK), EntityID (FK), {other fields})
Supplier (ID (PK), EntityID (FK), {other fields})
Telephone (ID (PK), EntityID (FK), Value)
This also has the added advantage of reducing duplication between Customer and Supplier.

A good design would be
Customers: Table of customers - CustomerId, Other columns
Suppliers: Table of suppliers - SupplierId, Other columns
Telephones: Table of telephones - TelephoneId, other columns
CustomerTelephones: CustomerId, TelephoneId
SupplierTelephones: SupplierId, TelephoneId

my advise is that you assign an ID for the table then add a reference field with the same datatype with the SupplierID and CustomerID

The other answers are decent beginner solutions, but they all have the same fundamental flaw in that Customer or Supplier are Relationships and not their own unique entities. A Customer is not a person, it's a relationship between you and a person.
In fact a person could be an Employee, Customer, Supplier all at the same time, or over time.
A Customer or Supplier could also be a Business, with many involved people.
Here is the correct answer:
PARTY
id
type {individual, organization, automated_agent}
org_name null
first_name null
last_name null
PARTY_RELATIONSHIP
from_party_id FK PARTY
type {supplier_of, customer_of, ...}
to_party_id FK PARTY
from_date
to_date null
Usage:
Insert into party (id, type, org_name) values (1, 'organization', 'Raw Steel Co');
Insert into party (id, type, f_name, last_name) values (2, 'individual', 'Davide', 'X');
-- Raw Steel Co is both a customer of and supplier to you:
Insert into party_relationship values (1, 'supplier_of', 2, getdate(), null);
Insert into party_relationship values (1, 'customer_of', 2, getdate(), null);
Now, some people don't like Single Table Inheritance because of the nulls, but goddam it is easier to work with. Use Class Table Inheritance if you're finicky.
The 'type' columns should be foreign keys to type tables.

you can do like
Customers: Table of customers - CustomerId, Other columns
Suppliers: Table of suppliers - SupplierId, Other columns
Telephones: Table of telephones - TelephoneId,TypeId,TypeName, other columns
where TypeName will be Customers or Suppliers, ant TypeId will be id of the resp.

Related

How do i update a column with specific values to reference the primary key ID of another table?

My goal is to normalize my table. My table before normalization is called Product Specifications, to normalize it I have two other tables called buyers_table and product_table
Table "Product Specifications"
Columns: Product_id , model_number, buyer
Buyers_table
Column: Buyer_id, buyer
Product_table
product_id, model_number, buyer_id
How do I insert the buyers from my product_specification table into my product_table but have the values show up as the buyer_id value instead of buyer?
Sorry I am new to this. This is a simplified version of the database that I have set up for my company.
use this design for database
Product_buyer: Columns:Id, Product_id , Buyer_id
Buyers_table: Column: Id, Buyername
Product_table: Id, Model_number
Product_Specifications: Id,Product_id,Productname,Price
then For insert data to database
First enter the information in the Product_table table
Retrieve the latest Product_table table record and enter Id as Product_id and the other of the information in the Product_Specifications table.
Enter the buyer information in the Buyers_table table when purchasing
Product_buyer
Create tables
create table Product_table
(
Id int identity,
Model_number int,
primary key(Id));
create table Product_Specifications
(Id int identity,
Product_id int,
Productname nvarchar(150),
Price int,
primary key(ID),
foreign key(Product_id) references Product_table);
//**********************
//and define other table
//......................
Retrieve product information
select Product_table.Id,Product_table.Model_number,Product_Specifications.Productname,Productname.Price
from Product_table join Product_Specifications
on Product_table.Id = Product_Specifications.Product_id
Retrieve Product_buyer information
select Product_table.Id,Product_table.Model_number,Product_Specifications.Productname,Productname.Price,Buyers_table.Id,Buyers_table.Buyername
from Buyers_table join Product_buyer on Buyers_table.Id = Product_buyer.Buyer_id
join Product_table on Product_buyer.Product_id = Product_table.Id
join Product_Specifications on Product_table.Id = Product_Specifications.Product_id

SQL creating a join between two tables

I want to create three tables.
Orders (contains an order ID and a customer name)
Products (contains a Product ID, description, and price)
Line Item (contains Order ID, Line Item ID, Product ID, and Quantity)
I want my web app to allow a customer to select an order number, and as a result, it will display the products that are in that order, the quantity of said products, the price of the products, and a total price of order that will be calculated on the fly in my code behind.
My SQL looks like this
CREATE TABLE Products
(
ProductID int NOT NULL,
ProductDescription varchar(MAX) NOT NULL,
ProductPrice smallmoney NOT NULL,
PRIMARY KEY (ProductID)
)
CREATE TABLE Orders(
OrderID int NOT NULL,
CustomerName varchar(MAX) NOT NULL,
PRIMARY KEY (OrderID)
)
CREATE TABLE LineItem(
LineItemID int NOT NULL,
OrderID int NOT NULL FOREIGN KEY REFERENCES Orders(OrderID),
ProductID int NOT NULL FOREIGN KEY REFERENCES Products(ProductID),
Quantity int NOT NULL,
PRIMARY KEY (LineItemID)
)
Here is the database diagram with the relationships.
Here is the result of a select all statement on all the tables
Are my relationships set up correctly for what I want to achieve? I'm sorry if this seems simple but I'm new to this and while the SQL Statements are pretty easy, the way to relate tables is not.
SELECT p.ProductPrice, p.ProductDescription, o.CustomerName, l.Quantity
FROM LineItem AS l
INNER JOIN Products AS p ON l.ProductID=p.ProductID
INNER JOIN Orders AS o ON l.OrderID=o.OrderID
ORDER BY l.LineItemID
will provide combined information from all of these tables. You may add any additional columns which you want to fetch data from.
INNER JOIN and JOIN keywords are syntactic sugar, which have same effect. While you're binding two tables by INNER JOIN, only results which contained in both of these tables will be returned.
With the ON keyword, you are defining the relational columns of tables. For example, in the clause INNER JOIN Products AS p ON l.ProductID=p.ProductID, I'm defining that the data are relational in column ProductID of table Products with column ProductID of table LineItem.
You have a many-to-many relationship between Products and Orders so in the structure of LineItem table I think you already have have the primary key (Product Id,OrderID) and I think you do not need to LocalItemID
CREATE TABLE LineItem(
OrderID int NOT NULL FOREIGN KEY REFERENCES Orders(OrderID),
ProductID int NOT NULL FOREIGN KEY REFERENCES Products(ProductID),
Quantity int NOT NULL,
PRIMARY KEY (OrderID ,ProductID )
)
and you can join the tables using this:
SELECT p.ProductPrice, o.CustomerName, li.Quantity
FROM LineItem AS li
JOIN Products AS p ON li.ProductID=p.ProductID
JOIN Orders ON li.OrderID=o.OrderID

database relations issue

I have a question regarding my database design and its implementation that i am hoping someone can help me with?
I have a product -> retailer scenario where by the following rules apply:
product - many retailers
product - 1 brand
retailer - many products
Price can change per retailers
so i have 4 tables
product - (Product_ID), product name, brand_ID(FK), details
brand - (Brand_ID), brand name
retailer - (Retailer_ID), retailer_Name, Retailer_Telephone
Retailer_Product - (Product_ID, Retailer_ID), cost,
This works fine as you can associate products with reatilers and not all retailers offer all products etc. each product has a set brand.
My issues comes based on the brand:
a retailer can offer 1 or more brands but not necessarily all brands? i am getting an issue implementing this?
So i have created a Retailer_Brand table
retailer_brand - (retailer_Id, Brand_ID)
Even if you have specified the retailer to brand link i can still enter a product into the retailer product table that is of a brand not associated with the retailer. Am i missing something like a check constraint or is my schema wrong?
Thanks
Rob
*EDIT further details *
I am still not sure if it gives me what I require.
Perhaps If I add the following example it will clarify.
I have a list of products setup that we can offer
e.g.
Name Desc Brand
TV 32 Inch Sony
TV 64 Inch Sony
TV 20 Inch Sony
TV 64 Inch Samsung
TV 32 Inch Samsung
TV 32 Inch Panasonic
Retailers
Uberhardware - Can sell all brands of tv
SonyRetailer - Is only allowed to sell Sony products (all products)
PanasonicRetailer - Panasonic Products only
Then along comes a new retailer who I need to setup:
Phoenix Retail - Is not allowed to sell Sony products
I wish to be able to easily restrict/enable the different brands per retailer?
EDIT 2
I have implemented the Alternate key design suggested but i am still able to enter incorrect date see my data setup below and the expected results however all enrtsy into the retailer product table succeed when i would expect some to fail?
Product
ProductID BrandID
1 1
2 2
Brand
BrandID
1
2
Reatiler
1
2
RetailerBrand
RetailerID BrandID
1 1
2 1
2 2
3 1
RetailerProduct
RetaileID Brand ProductID Expected
1 1 1 OK
1 2 2 FAIL
2 1 1 OK
2 2 2 OK
3 2 2 FAIL
Alternate key (AK) -- unique constraint (with index) on Product allows (ProductID, BrandID) to be referenced from RetailerProduct as a FK.
create table Product (
ProductID integer not null
, BrandID integer not null
);
alter table Product add constraint pk_product primary key (ProductID);
alter table Product add constraint un_product unique (ProductID, BrandID);
create table Brand (
BrandID integer not null
);
alter table Brand add constraint pk_brand primary key (BrandID);
create table Retailer (
RetailerID integer not null
);
alter table Retailer add constraint pk_retailer primary key (RetailerID);
create table RetailerBrand (
RetailerID integer not null
, BrandID integer not null
);
alter table RetailerBrand add constraint pk_retbra primary key (RetailerID, BrandID);
create table RetailerProduct (
RetailerID integer not null
, ProductID integer not null
, BrandID integer not null
);
alter table RetailerProduct add constraint pk_retprd primary key (RetailerID, ProductID, BrandID);
alter table RetailerProduct add constraint fk1_retprd
foreign key (ProductID, BrandID) references Product (ProductID, BrandID);
alter table RetailerProduct add constraint fk2_retprd
foreign key (RetailerID, BrandID) references RetailerBrand (RetailerID, BrandID);
EDIT
Insert some data
insert into Brand (BrandID) values (1) , (2);
insert into Product (ProductID, BrandID) values (1,1), (2,2);
insert into Retailer (RetailerID) values (1) , (2);
insert into RetailerBrand (RetailerID, BrandID) values (1,1), (2,1), (2,2), (3,1);
Test
insert into RetailerProduct (RetailerID, BrandID, ProductID) values (1,1,1); -- OK
insert into RetailerProduct (RetailerID, BrandID, ProductID) values (1,2,2); -- FAIL
insert into RetailerProduct (RetailerID, BrandID, ProductID) values (2,1,1); -- OK
insert into RetailerProduct (RetailerID, BrandID, ProductID) values (2,2,2); -- OK
insert into RetailerProduct (RetailerID, BrandID, ProductID) values (3,2,2); -- FAIL
Let me see if I get this right.
Product
product_id
name
description
etc
Brand
brand_id
name
etc
Retailer
retailer_id
name
etc
Relational table
brand_prod_ret
retailer_id
product_id
brand_id
price
etc
For example, Uberhardware retailer sells TVs: LG, Sony, Samsung, etc.
Uberhardware goes in the Retailer table
TVs goes into the Product table
You have product_id matched with retailer_id and brand_id in the brand_prod_ret table.
Into brands you have LG, Sony, Samsung, etc.
and into brand_prod_ret you have
TVs' ID - Sony's id -Uberhardware id
TVs' ID - Samsung's id - Uberhardware id
TVs' ID - LG's id - Uberhardware id
and of course each price.
Now you can know exactly which brand the retailer is selling at the moment
Is there any reason the brand table is needed in this capacity?
We have many to many relationships with
products - brand
retailer - retailer_product
brand - retailer brand
Seems you could keep the brand info in the retailer_product table. Then every new brand entered could be pk linked. Or only a retailer to brand look up table to enforce the constraint of a retailer association b/f a new retailer_product can be entered
IMO in your current structure, the table retailer_brand is not strictly necessary, as you can always determine which brands are fully or partially stocked by a retailer by navigating through the retailer_product => product => brand relations.
Can I ask for some clarification on your business domain which might impact your data modelling? (I have some experience at a retailer), e.g.
Brands are often retailer-specific (i.e. a Supplier manufactures a line of products branded purely for one retailer). You might consider adding a Supplier table to your model.
Often stores within the retailer's chain do not stock all products. You might need to consider this in your model.
I'm not sure whether you are on the consumer or supplier facing side of the business, but you may need to model both a cost price and a selling price.
Prices should include Date From / Date To
etc.

Avoiding duplicates in designing One to Many relationship

I went through many threads and couldn't figure it out. Sorry if this is a duplicate question. Consider the following setup.
1) Employee => (ID,Name)
2) Department => (ID,Name,location,Clerk,Accountant,Middle-manager,Group-manager,Regional-manager,Active)
Department can have many Clerks, Accountants, Middle-managers and so on. They are just employees from the Employee table. Need a better database schema (flexible like, adding up a new column as Divisional-Manager must be easy) for Department entity with NO data duplication, NO update anomalies and NO / less junction tables.
Thanks in advance! :)
You need something like this;
CREATE TABLE department(
dept_id int NOT NULL,
dept_name char(10) NULL,
CONSTRAINT PK1 PRIMARY KEY NONCLUSTERED (dept_id)
)
go
CREATE TABLE department_employee(
id int NOT NULL,
dept_id int NOT NULL,
emp_id int NOT NULL,
CONSTRAINT PK3 PRIMARY KEY NONCLUSTERED (id)
)
go
CREATE TABLE employee(
emp_id int NOT NULL,
emp_name char(10) NULL,
CONSTRAINT PK2 PRIMARY KEY NONCLUSTERED (emp_id)
)
go
ALTER TABLE department_employee ADD CONSTRAINT Refdepartment1
FOREIGN KEY (dept_id)
REFERENCES department(dept_id)
go
ALTER TABLE department_employee ADD CONSTRAINT Refemployee2
FOREIGN KEY (emp_id)
REFERENCES employee(emp_id)
go
You have a many-to-many relationship so you need a third association (junction) table - you can't avoid it.
DepartmentMember => (DepartmentId, EmployeeId, MembershipRole)
Why don't you want this?
Employee =>(ID,name, department_ID, position_ID, Active)
Position =>(ID, name, Active)
Department => (ID,Name,location,Active)
Department =>(ID,employeeID,location,active)
Employee =>(EmployeeID,name, position)
I think that would be a much better way of organizing your tables. This assumes that active is a property of the department, else move it to the employee table.
Assuming an employee can only work in 1 department. IF not, then yes, you need a third table to avoid duplication
Employee
ID, Name, EmployeeType, DepartmentID
(pk on ID, EmployeeType)
Department
ID, Name, Active
Position/Title is very much contextual
to Department. One can be a
Regional-Manager in one department and
can additionally takes Consultant
position in another department.
Then , the department and the Employee is many-to-many. The Employee to the position is also many-to-many. If you need flexibility ,like adding a new title for a department , the junction tables are necessary. You cannot avoid it.
You can refer to the following Table structure for reference:
Employee
-----------------------
EmployeeID (PK)
EmployeeName
Active
Department
-------------------------
DepartmentID (PK)
DepartmenName
Location
Position
----------------------------
PositionID (PK)
PositionDescription (eg.Clerk, Accountant etc)
EmployeePosition
----------------------------
EmployeeID (FK to Employee.EmployeeID )
DepartmentID (FK to Department.DepartmentID)
PositionID (FK to Position.PositionID )
If the Position/Title is fixed to
Employee instead of Department.i.e. An
employee who is clerk and can be in
that position to one or many dept.,
how can we go about it?
Do you mean that in an extreme case , many employees can have their own special titles ? and they belong to many departments? If yes ,suppose a employee ID 123 has a special title called "The Special One" , and it belongs to the IT , Account and Sales department . You first create this title (i.e "The Special One" ) in the Position table and get the Position.PositionID.
Then you insert 3 records for Employee.EmployeeID 123 into EmployeePosition table using this Position.PositionID and the Department ID of IT , Account , Sales departments.

Different user types / objects own content in same table - how?

Any idea how I can relate different objects together? Usecase i am trying to achieve is Comments are usually owned by a user. So i have a user_id for it. But I have company pages also where the company owns the content on its page so the owner is the company_id. (Which ofcoure is admin by several users)
One way is to have 2 tables user_comments and company_comments but the problem is then i need 2 tables per object and if i add more user types then i need to multiple the tables. What i want to achieve is 1 table which has:
comment_id PK
owner_id (user id or company id or etc...) - fk?
So let's say i create a owner table just to link all user types together, what would the columns be to get these all in or is there some other way?
People and organizations are a good example of things in a supertype/subtype relationship. They are not identical, but they are not utterly distinct. They share many attributes. Both people and organizations have addresses and telephone numbers, both people and organizations can be plaintiffs and defendants in a lawsuit, and both people and organizations can apparently own comments in your system.
To implement this in a SQL dbms, put the columns common to both people and organizations in one table called, say, "Parties". Columns unique to people go in a table of people; columns unique to organizations go in a table of organizations. Use views, one per subtype, to hide the implementation details; your clients use the views, not the tables.
You'd use the key from the supertype table, "Parties", as the owner of your comments. (I think.)
Here's a simplified example.
create table parties (
party_id integer not null unique,
party_type char(1) not null check (party_type in ('I', 'O')),
party_name varchar(10) not null unique,
primary key (party_id, party_type)
);
insert into parties values (1,'I', 'Mike');
insert into parties values (2,'I', 'Sherry');
insert into parties values (3,'O', 'Vandelay');
-- For "persons", a Subtype of "parties"
create table pers (
party_id integer not null unique,
party_type char(1) not null default 'I' check (party_type = 'I'),
height_inches integer not null check (height_inches between 24 and 108),
primary key (party_id),
foreign key (party_id, party_type) references parties (party_id, party_type)
);
insert into pers values (1, 'I', 72);
insert into pers values (2, 'I', 60);
-- For "organizations", a subtype of "parties"
create table org (
party_id integer not null unique,
party_type CHAR(1) not null default 'O' check (party_type = 'O'),
ein CHAR(10), -- In US, federal Employer Identification Number
primary key (party_id),
foreign key (party_id, party_type) references parties (party_id, party_type)
);
insert into org values (3, 'O', '00-0000000');
create view people as
select t1.party_id, t1.party_name, t2.height_inches
from parties t1
inner join pers t2 on (t1.party_id = t2.party_id);
create view organizations as
select t1.party_id, t1.party_name, t2.ein
from parties t1
inner join org t2 on (t1.party_id = t2.party_id);
Make the view updatable using whatever feature your dbms provides to do that. (Probably triggers.) Then application code can just insert into the appropriate view.

Resources