Establishing a one to many relationship between 2 tables - sql

I am building a database which consists of a
table of category, customer table, and table of product which fetches information from categories.
Now I need a new table for sale which consists of customerID, date, productID. My problem is
the customer may buy many products. how can I make the relation between them in SQL Server 2008?

Customer {id, name, ...}
Product {id, name, ...}
Sale {product_id, customer_id, order_id, qty, ...}
Order {id, date, ...}

Just add a order table, the order table will keep reference to the products in the order.

Your drawing commented on in #orn's answer only makes sense if each sale can only involve one product.
Mr Fliim put you on the right track to deal with multiple products in one sale.

Related

When I try to output the customerName and customerID of people who have rented films priced 2.6, it outputs the name and ID of everyone

SELECT customerId, customerName
FROM customerRentalinfo, film
WHERE filmPrice = 2.6;
This is the table that I have created for the movie rental system. rental id, customer id, customer name, customer email, rental date, film name, quantity, film price, total price are the entities of this table:
This is too long for a comment. You cannot answer the question with the given data model, assuming that the column names are even remotely related to what they actually represent.
In particular:
The customer is attached to rentalId, which leads to filmName.
The two tables with a price have no film id or name at all. They are just prices sitting on unidentified rows.
The data model has other issues as well:
Customer information is repeated separately for each rental. Such information should be in a single Customers table.
The price would normally be in only one table.
The films table would normally have an id and a name.
In fact, every table should have an id.
And no doubt other problems as well.
I will also throw in that you should be using proper, explicit, standard, readable JOIN syntax. Never use commas in the FROM clause.

Price comparison database - put price data in main table, in one separate table or in many product tables?

I'm trying to build a price comparison database with n products and a definitive but changing number of vendors that sell these products.
For my price comparison database, I need to store both current prices for a product across different vendors and historical prices (one lowest price).
As I see it, I have 2 options to design the database tables:
1. Put all vendor prices into the main table.
I know how many vendors there will be and if I add or remove a vendor I can add or remove a column.
Historical prices (lowest price on certain date across all vendors), goes into a separate table with a product name, a price and a date.
2. Have one table for products and one table for prices
I will have only the static attribute data in the main table such as categories, attributes etc and then add prices to a separate product table where I store price, vendor, date in it and I can store the lowest price as a pseudo-vendor in that table for each date or I can store it in a separate table as well.
Which method would you suggest and am I missing something?
You should store the base data in a normalized format that contains all the history. This means that you have tables for:
products, with one row per product and the static information about the products.
vendors, with one row per vendor and the static information about the vendor.
prices, with one row per price along with the date and product and vendor.
You can get the current and lowest prices using a query, such as:
select pr.*
from (select pr.*, min(price) over (partition by product) as min_price
row_number() over (partition by product, vendor order by price_datetime desc) as seqnum
from prices pr
where pr.product_id = XXX
) pr
where seqnum = 1;
For performance, you want an index on prices(product, vendor, price_datetime desc).
Eventually, you may find that this query runs too slowly. In that case, you will then consider optimizations. One optimization would simply be storing the latest date for each price/vendor combination using a trigger, along with the minimum price in the products table -- presumably using triggers.
Another would be maintaining a summary table for each product and vendor using triggers. However, that is probably not how you should start the endeavor.
However, you might be surprised at how well the above query can perform on your data.

How would I structure a database for taking sales orders?

I am helping someone build a grocery deliver service. Very simple site and order process. The problem I am having is knowing how to come up with schema for the orders. The order would have contact information, but would also need to have all of the products they ordered. Since it can/will be different for each persons order, how would I go about designing this? Would I just have a products ordered field with a string list of all the items? Or would I need multiple linked tables?
Thanks!
You need three tables:
a) Products - Contains the product details
b) Orders - Contains the order header, contact information etc
c) Product_Orders - is a table with two columns: product_id and order_id, that bind the orders to the products, and a quantity field and unit price.
You could have a customers table, but ideally information like the delivery address, etc, would be attached to the order so that if the user changes his address it will not affect your order history.
For the same reason unit price must be in Product_Orders, so that if a product price changes it does not affect previous orders.
Product table
with name and price of all products.
Customer table
with name, address, phone etc...
Order table
with entries for each order: order id, cusomer id, date etc
Order Items table
with all ordered items, with link to id in ordertable, product table, quantity, price, etc...

linking child tables of two related parent-child tables

I have two parent child tables and a couple of supporting tables. I am struggling to figure out the right relationships between them.
Orders, a table that holds a list of Orders including:Order Id, Supplier, Order Date etc..
OrderDetails, a Table holds a list of products that have been ordered, and is a child of Orders, linked on OrderId. Key fields are the ProductId and the Quantity Ordered. Each order containes one or many OrderDetails that outline the products and quantities being ordered.
Shipments, a table that holds a list of Shipments, including Tracking Number and Shipper. Links to Orders through Order Id. An Order may have multiple shipments. For example, I ordered 100 lightbulbs. They were dispatched in 5 shipments.
ShipmentDetails, holds a list of product and shipped quantities and is linked to the Shipments table by ShippingId. Each Shipment may have multiple ShipmentDetails. i.e. One shipment may have 30 Lightbulbs and 10 Door Knobs.
Products is a table that holds a list of Products that need to be both ordered and shipped.
So the logic is that I enter details about the products that are to be ordered in Products. For example, 100 CREE LED Lightbulbs, and 50 Door Handles.
When I place an order, I create an Order in Orders.
i.e. amazon.com, order #45454.
Then I add child rows to that order in OrderDetails. i.e. 30 CREE LED Lightbulbs.
When the order Ships, I create an entry in the Shipments table. i.e. Tracking #46464646464, linked to OrderId in Orders. And then I enter what is in that shipment in ShipmentDetails. For example, only 20 or the 30 CREE LED Lightbulbs may be associated with this Shipping entry.
I am struggling with figuring out how to relate the Shipping Detail records to the Order Detail Table. Lets say the Shipping Detail Table has 4 fields.
ShippingID - a link to the Shipments table parent.
TrackingNum - a field that holds a tracking number.
Product - this should be a drop down, that says, the shipment I belong to is related to a defined Order (because ShipmentDetail is a child of a Shipment record which in turn holds a key to the Orders table, which in turn has OrderDetails that reference products).
Quantity - this should have a default (overridable) value that is the "Quantity Ordered" number from the OrdersDetail record that matches the Order Id and Product Id. Where OrderId is in the Shipments table (linked to the Orders table) and ProductID comes from #3 above. The reason it must be overridable is that a shipment may be a partial shipment.
I am stuck with the preceding #3 and #4. I hope I have explained this in a vaguely understandable way! The pictures below may help!
The ask:
What is the correct join between the ShipmentDetails and the OrderDetail Table
How do I create a field in the ShipmentDetail table with a default value pulled from the Quantities Field of the OrderDetail table, where
Shipments!OrderId = Orders!Id and ShipmentDetail!ProductID = OrderDetails!Product ID
I am working in MS Access 2016 - but I suspect this is a fairly generic SQL question...rather than MS Access specific.
I think the naming is confusing.
What I would rather have is (each first id is autoincrement, forgot how to say this on access):
// Product doesn't contain any information about quantity/price etc ...
create table Products(product_id int, name text, description text ...);
// Orders:
create table Orders(order_id int, client_name text, description text ...);
create table OrderDetails(order_detail_id int, order_id int, product_id int, quantity double, unit_price double, ...);
// Shipments
create table Shipments(shipment_id int, company text, description text ...);
create table ShipmentDetails(shipment_detail_id int, shipment_id int, product_id int, quantity double, price double default 0, ...);
// inserting shipments per product (defaulting to total quantity per product), assuming we have shipment_id SID
insert into ShipmentDetails(shipment_id, order_id, product_id, quantity)
select SID, order_id, product_id, SUM(quantity)
from OrderDetails
group by order_id, product_id;
Then you can of course have some filters (date, customer etc ...).
For the first question, I am not clear what exaclty you want to return.
Here is a comparison of quantities:
select t.order_id, t.product_id, sum(t.quantity) as product_quantity, sum(u.quantity) as shipment_quantity
from OrderDetails t inner join ShipmentDetails u
on t.order_id = u.order_id and t.product_id = u.product_id;

SQL; How to insure data integrity in complex situations

I have three tables named, Customer , Product , Sale . I need to know which products has been presented in which Sales and which customers have been attended to which Sales. So here is what we have so far:
Customer (Id, Name)
Product (Id, Name)
Sale(Id, Title, Date)
CustomerSale(Id, CustomerId, SaleId) //intermediate table
ProductSale(Id, ProductId, SaleId) //intermediate table
Also I need to know which customer likes (just imagine they can up-vote products!) which products in each Sale and also I need to know which customer mark which product as useful in each Sale. So I have two solutions:
Scenario 1: simply make an intermediate table between those two intermediate tables!
CustomerProduct(Id, customerSaleId, productSaleId, doesLikes, isUseful)
Scenario 2: make an intermediate with FK to three tables (Customer, Product, Sale)!
CustomerProduct(Id, SaleId, CustomerId, ProductId, doesLikes, isUseful)
Problem:
None of the above solutions insure data integrity because in scenario1 it is possible to insert customerSaleId and productSaleId which does not refer to the same Sale. In scenario2 it is possible to insert an invalid (Sale, Customer, Product) triple. because you cannot be sure whether the product is presented in that Sale or not moreover you cannot be sure the customer has attended to that sale or not.
So is there any better solution?
If you ignore the surrogate keys on CustomerSale and ProductSale and have scenario 2 reference the compound unique keys on these tables of (CustomerId, SaleId) and (ProductId, SaleId) respectively would this give you what you want?
I change your structure to this
Customer (Id, Name)
Product (Id, Name)
Sale(Id, CustomerId, Title, Date)
ProductSale(Id, ProductId, SaleId)
CustomerProduct(Id, productSaleId, doesLikes, isUseful)
isn't it better?