I am trying to figure out an effective and efficient way to implement the following relationship between two tables, Lists(ListID, ListName) and Items(ItemID, ItemName, Cost, Description, QuantityNeeded, QuantityPurchased), in a MySQL database:
A list can have many items. However, the Description, QuantityNeeded, and QuantityPurchased attributes in the Items table are specific to a list. For example, say one item has the attributes 1, Paper Towels, 5.99, NULL, 4, 2, and another is 2, Paper Towels, 5.99, NULL, 7, 0. Even though these have the same ItemName and Cost, they are from different lists.
What is the best way I can go about implementing this? I have thought about adding an attribute ListID to the Items table so that every item "knows" which list it is a part of, but this could result in really lengthy WHERE executions (correct?), and I want this to be as efficient as possible.
Application relationships are not between tables, they are among values (or entities so identified) and are represented by tables.
Add
-- list ListID has member ItemId
-- UNIQUE/PK (itemID)
-- FK (listID) references Lists
-- FK (itemID) references Items
Member(ListID, itemID)
Or replace Items by
-- list ListID has member ItemId and item ItemId ...
-- UNIQUE/PK (ItemID)
-- FK (ListID) referencing Lists
ItemsX(ListID, ItemID, ItemName, Cost, Description, QuantityNeeded, QuantityPurchased)
The former is difficult to constrain in SQL to also have the equivalent of FK Items (ItemID) referencing Member, ie every item must be a member of some list. So typically the latter would be used.
Note that
ItemsX = ListID, i.* from Member m join Items i on m.ItemID = i.ItemId
Items = select ItemID,... from ItemsX
Member = select ListID, ItemID from ItemsX
If you don't know the options for straightforward models, you don't know enough to worry about "efficiency". You need more design (including constraints) & querying experience. Your situation is addressed in practically any intro to information modeling via orders & order (line) items instead of lists & items.
Related
I'm designing a relational database tables for storing data about eCommerce scenario where I need to store
List of Products purchased by a user
List of users who purchased a particular product.
Its a many to many relationship.
So far I could only thinking of doing this.
create a table for storing orders
table recordorders(
userID // foreign key from users table
productID, // foreign key from products table
dateofpurchase,
quantity,
price_per_unit,
total_amount
)
It will act like a junction table.
Is this a good approach and are there any other methods than junction table that are more effective and efficient for querying ?
Your bullets describe two tables, not one. Your junction table is not properly described as two lists. It is a set of order info rows. The junction table you gave holds rows where "user [userID] purchased product [productID] on ...". Ie it records order info. (Combinations of user, product, date, etc of orders.) Given a user or product, you can get the corresponding bullet table by querying the order info table.
However your table probably needs another column that is a unique order id. Otherwise it cannot record that there are two orders that are alike in all those columns. (Eg if the same person buys the same product on the same date in the same quantity, price and total.) Ie its rows probably aren't 1:1 with orders. That's why above I called it an order info table rather than an order table. It records that some order had those properties; but it doesn't record distinct orders if there can be orders with the same info. It's really a many-to-many-to-etc (for every column) association. That is why an order id gets picked as a unique name for an order as further info. This new table would be called an entity table, not a junction or association table. It holds rows where "in order [id] user [user] purchased ...".
PS An order is usually something that can be characterized as an association on/among/between an order id, user, set of order-lines (product, quantity, price & total), and other stuff (date, grand total, etc). The orders are usually relationally characterized by an order entity table on order id with its user, date etc plus an order-line association table on order ids and their order-line info.
PPS It's time for you to read a book about information modeling and database design.
You don't "store" those two things in a table (Junction, or otherwise), you discover them from the raw ("Fact") data:
Using your proposed table:
List of Products purchased by a user:
SELECT productID
FROM recordorders
WHERE userID = 123;
List of users who purchased a particular product:
SELECT userID
FROM recordorders
WHERE productID = 987;
I understand - and have created - a self-referencing table that contains Categories & Subcategories. SO, you get a table that looks like this:
Categories Table:
id, primary Key autoNumber
category, text
parentID, foreign Key, number
categories.ID has a one-to-many relationship with categories.parentID
==Here is what I'm having a really tough time understanding==
I also have a Transactions table used to track a purchase, and two columns to record the Category and its Subcategory. Think "Automobile: Gasoline", or "Healthcare: Prescriptions".
Transactions Table:
id, primaryKey, autoNumber
payee, shortText
Category, foreign key, (number, comboBox)
Subcategory (number, comboBox)
categories.ID has a one-to-many relationship with Transactions.Category
I can't find the appropriate way to populate Category and Subcategory in the Transactions table.
So far, I was able to pull all distinct categories from the Categories Table with a SQL statement similar to the example below. (Any Category with a NULL parentID is considered a root category).
SELECT *
FROM Categories
WHERE (((Categories.[parentID]) Is Null))
ORDER BY Categories.category DESC;
My problem is finding a way to get Transactions.Subcategory to list only the subcategories associated with the chosen root category.
I don't know how to do this in Access.
Any tips, advice, etc., would be very much appreciated.
i'm building a study tool and i'm not sure of the best way to go about structuring my database.
Basically, i have a simple but big table with around 50000 bits of information in it.
info (50'000 rows)
id
info_text
user
id
name
email
password
etc
What i want is for the students to be able to marked each item as studied or to be studied(basically on and off), so that they can tick off each item when they have revised it.
I want to build tool to cope with thousands of users and was wondering what the most efficient/easiest option way of setting up the database and associated queries.
At the moment i would lean towards just having one huge table with two primary keys one with user id and then id of the info they had studied and then doing some sort of JOIN statement so i could only pull back the items that they had left to study.
user_info
user_id
info_id
Thanks in advance
Here is one way to model this situation:
The table in the middle has a composite primary key on USER_ID and ITEM_ID, so a combination of the two must be unique, even though individually they don't have to be.
A user (with given USER_ID) has studied a particular item (with given ITEM_ID) only if there is a corresponding row in the STUDIED table (with these same USER_ID and ITEM_ID values).
Conversely, the user has not studied the item, if and only if the corresponding row in STUDIED is missing. To pull all items a given user hasn't studied, you can do something like this:
SELECT * FROM ITEM
WHERE NOT EXISTS (
SELECT * FROM STUDIED
WHERE
USER_ID = <given_user_id>
AND ITEM.ITEM_ID = STUDIED.ITEM_ID
)
Or, alternatively:
SELECT ITEM.*
FROM ITEM LEFT JOIN STUDIED ON ITEM.ITEM_ID = STUDIED.ITEM_ID
WHERE USER_ID = <given_user_id> AND STUDIED.ITEM_ID IS NULL
The good thing about this design is that you don't need to care about STUDIED table in advance. When adding a new user or item, just leave the STUDIED alone - you'll gradually fill it later as users progress with their studies.
I would do something like this:
1) A users table with a uid primary key
2) A enrolled table (this table shows all courses that have enrolled students) with a primary key of (uid, cid)
3) A items (info) table holding all items to study, with a primary key of itemid
Then in the enrolled table just have one attribute (a binary flag) 1 means it has been studyed and 0 means they still need to study it.
This has been driving me mad.
I have three tables:
items
ID
name
type
cats
ID
name
items_to_cats
FK_ITEM_ID
FK_CAT_ID
This is a simple many-to-many relationship. I have items and categories. Each item can be linked to one or more categories. This is done via a simple joining table where each row maintains a relationship between one item and one category using foreign key constraints.
You will notice that my "items" table has a field called "type". This is an indexed column that defines the type of content stored there. Example values here are "report", "interview", "opinion", etc.
Here's the question. I want to retrieve a list of categories that have at least one item of type "report".
Ideally I want to get the result in a single query using joins. Help!
select distinct cats.id, cats.name
from cats
join items_to_cats on items_to_cats.fk_cat_id=cats.id
join items on items.id=items_to_cats.fk_item_id
where items.type='report'
Just as a point of database design, if you have a small set of legal values for items.type, i.e. "report", "interview", "opinion", maybe a couple more, then you really should create a separate table for that with, say, an id and a name, then just put the type id in the items table. That way you don't get into trouble because somewhere it's mis-spelled "raport", or even more likely, someone puts "reports" instead of "report".
or how about this :
SELECT c.id, c.name
FROM cats c
WHERE c.id IN
(SELECT ic.fk_cat_id
FROM items_to_cats ic
JOIN items i on i.id=ic.fk_item_id
WHERE items.type='report'
)
Amazon has "Customers Who Bought This Item Also Bought".
I am wondering and want to add this to my shopping cart which I made.
What fields do I need in a database? Any website, blog or resources for this?
Can you suggest the mechanism how to I should code it please?
Here are some similar questions:
How do recommendation systems work?
Design of the recommendation engine database?
How to create my own recommendation engine?
Techniques for building recommendation engines?
Where can I learn about recommendation systems?
You probably don't need any new fields in your database - just keep a history of your orders. Then when you want to find your list of what other people bought:
Select all users who have an order containing Item X
For each of those users, total up everything else they have bought
Get the top 3/5/whatever and there's your list.
It's not too tricky. Assume you have the following tables:
Customers, primary key CustomerID
Products, primary key ProductID
Orders, primary key OrderID, foreign key CustomerID
OrderItems, primary key OrderItemID, foreign keys OrderID, ProductID
To find the products you seek, you need to find the set of customers who have bought that particular product ID:
SELECT CustomerID
FROM (Customers INNER JOIN (Orders INNER JOIN OrderItems))
WHERE OrderItem.ProductID = <your product id here>
Then, you need to get the other products those customers have bought:
SELECT ProductID
FROM (Customers INNER JOIN (Orders INNER JOIN OrderItems))
WHERE (Customer = <given customer ID>) AND (ProductID <> <your product id>)
Then select the top few products and you're off to the races.
Note: I'm a numerical guy. The DB gurus will be able to do this in 1 query! :)
You need history of orders so that you can check for other items that were bought together with the item user is currently viewing.
You need "Programming Collective Intelligence". They have some nice chapters about recommendations and such. You'll want to read about Pearson differences and other measures.
Have a look at Algorithms of the intelligent web, chapter 3 "Creating suggestions and recommendations". For your question: optionally, you might need a table with user ratings for different items. Based on these ratings, you will be able to measure similarity between two clients and then perform an estimation based on these values on the items one of client is about to achieve. These estimations are used to rank the items.
Also, have a look at the Apriori algorithm chapter 4 or a general description of it here; this works for items bought together and extract some associations rules. Based on these rules, you will detect which of the items you sell might be added to the client's basket. For your question: no additional field should be added to your database; you have to maintain only a table to group items purchased together (market baskets contents).
select `A`.`ORDER_NO`, `A`.`SKU`, `B`.`SKU` `REL_SKU`
from `order_detail` `A`
inner join
(select DISTINCT `ORDER_NO`, `SKU`
from `order_detail`) `B`
on `B`.`ORDER_NO` = `A`.`ORDER_NO`
WHERE `B`.`SKU` = 'XXXXXXXX'
AND `A`.`SKU` <> 'XXXXXXXX'
This works for me. of course add in any filters in the where clause as appropriate such as order status etc...