Database Outline Design for Shopping cart - mysql

I'm looking for the best way to design a shopping cart. I'm at a crossroads with how to handle a product that has multiple options being color and size. The main issue being inventory management for the colors and sizes.
Currently on admin panel:
textfield for color
textfield for quantity
User seperates colors by comma along with quantity so color & quantity match when I explode/implode them into arrays, thus allowing me to manage the quantity whenever something is purchased by their keys after doing an array search for the color.
Right now I just have one table holding upc/name/color/quanity/price etc...
Should I be using some type of foreign key and having tables for color/quantity on their own?
This is more of a design question and not a show me exactly how to do it question as I'm just trying to learn the most optimum way to manage a database.
Thanks!

I'm not quit sure I understand your question but I think you are looking for suggestions on how to data model this and how to represent arrays of data from this model as strings that can be manipulated browser-side.
For the data model, it sounds like you need a 5 tables:
1) Product, 2) Color, 3) Size, 4) an associative table between Product and Color, 5) an associative table between Product and Size. Tables 4 and 5 implement the many-to-many relationships between products and the different colors offered, and between products and the different size offered.
Then you can settle on a standard way of representing shopping cart items as strings. Say:
<productId>,<qty>,<colorId>,<sizeId>
Arrays of these shopping cart items would be semicolon separated.
Looking for a way to represent the color and size choices for a particular product? I often use this type of query to retrieve choices as a comma-separated list which are then easy to deal with client-side:
-- =============================================
-- Author: Joe Blo
-- Create date: Jan 1, 2010
-- Description: Returns list of color choices for
-- a product in CSV format
-- =============================================
CREATE FUNCTION [dbo].[fn_GetProductColorsCSV]
(
#pProductUPC VARCHAR(30)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
-- Declare the return variable here
DECLARE #Result VARCHAR(MAX)
-- Add the T-SQL statements to compute the return value here
SELECT #Result = COALESCE(#Result + ',', '') + CAST(C.[ColorId] AS varchar)
FROM dbo.[ProductColorJunction] PCJ
INNER JOIN dbo.Color C ON C.[ColorId] = PCJ.Color
WHERE PCJ.ProductUPC = #pProductUPC
-- Return the result of the function
RETURN #Result
END

Why not start by exploring how open source shopping carts have handled similar tasks. osCommerce is one that comes to mind.

Use 3NF
http://www.troubleshooters.com/littstip/ltnorm.html
http://en.wikipedia.org/wiki/Third_normal_form

Related

What is the best way to merge 2 tables with Active Record and Mysql

We need to allow users to customize their entities like products... so my intention was to have a product table and a custom_product table with just the information the users are allowed to change.
When a client goes to the product I want to merge the information, means I want to merge the two tables - the custom overwrites the default Products table.
I know that in mysql there exists a ifnull(a.title, b.title) way but I was wondering if there is any nice and efficient way to solve this in Rails 4 with Active Record. Assume that the products and custom products table have just 2 columns, ID and TITLE
I think you can convert both objects to JSON and then handle their params as a hash, using the merge method:
class Product
end
class Customization
belongs_to :product
end
a = Product.find(...)
b = a.customization
c = JSON(a.to_json).merge(JSON(b.to_json).reject!{|k,v| v.nil?})
Therefore c will contain all params from Product eventually overridden by those in Customization which are not nil.
If you still want to use a Product object with hybrid values (taken from Customization) you can try this:
a.attributes = a.attributes.merge(b.attributes.reject!{|k,v| v.nil?})
In this case a will still be a Product instance. I would recommend to keep the same attributes in both models when doing this.

How to do a MYSQL conditional select statement

Background
I'm faced with the following problem, relating to three tables
class_sectors table contains three categories of classes
classes table contains a list of classes students can attend
class_choices contains the first, second and third class choice of the student, for each sector. So for sector 1 Student_A has class_1 as first choihce, class_3 as second choice and class_10 as third choice for example, then for sector 2 he has another three choices, etc...
The class_choices table has these columns:
kp_choice_id | kf_personID | kf_sectorID | kf_classID | preference | assigned
I think the column names are self explanatory. preference is either 1, 2 or 3. And assigned is a boolean set to 1 once we have reviewed a student's choices and assigned them to a class.
Problem:
Writing an sql query that tells the students what class they are assigned to for each sector. If their class hasn't been assigned, it should default to show their first preference.
I have actually got this to work, but using two (very bloated??) sql queries as follows:
$choices = $db -> Q("SELECT
*, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
`class_choices`
WHERE
(`assigned` = '1')
GROUP BY
`concatids`
ORDER BY
`kf_personIDID` ASC,
`kf_sectorID` ASC;");
$choices2 = $db -> Q("SELECT
*, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
`class_choices`
WHERE
`preference` = '1'
GROUP BY
`concatids`
HAVING
`concatids` NOT IN (".iimplode($choices).")
ORDER BY
`kf_personID` ASC,
`kf_sectorID` ASC;");
if(is_array($choices2)){
$choices = array_merge($choices,$choices2);
}
Now $choices does have what I want.
But I'm sure there is a way to simplify this, merge the two SQL queries, and so it's a bit more lightweight.
Is there some kind of conditional SQL query that can do this???
Your solution uses two steps to enable you to filter the data as needed. Since you are generating a report, this is a pretty good approach even if it looks a bit more verbose than you might like.
The advantage of this approach is that it is much easier to debug and maintain, a big plus.
To improve the situation, you need to consider the data structure itself. When I look at the class_choices table, I see the following fields: kf_classID, preference, assigned which contain the key information.
For each class, the assigned field is either 0 (default) or 1 (when the class preference is assigned for the student). By default, the class with preference = 1 is the assigned one since you display it in the report when assigned=0 for all the student's class choices in a particular sector.
The data model could be improved by imposing a business rule as follows:
For preference=1 set the default value assigned=1. When the class selection process
takes place, and if the student gets assigned the 2nd or 3rd choice, then preference 1 is unassigned and the alternate choice assigned.
This means a bit more code in the application but it makes the reporting a bit easier.
The source of the difficulty is that the assignment process does not explicitly assign the 1st preference. It only updates assigned if the student cannot get the 1st choice.
In summary, your SQL is good and the improvements come from taking another look at the data model.
Hope this helps, and good luck with the work!

Suggested DB Schema for Quotes

How would you save the quote products in a database? Serialize data?
http://cl.ly/6419969e30cd26e2f32a
They can create however many rows they want... It's for a quote system. Create a quote with however many products. I need to save X Product At X Qty and X Price foreach one.
Serialize in the only thing I could come up with, but I hate unserializing so very much. I didn't know if there was a quicker/more efficient way.
I also have all this information to store with / link with it http://cl.ly/40cc9fea47932b3740b2
PHP (Kohana) > mySQL
Thanks for any input you may have.
I would split the items on a quote into a separate child table:
Quote QuoteItem Item
========= =========== ============
QuoteID QuoteID ItemID
Subject ItemID Description
ValidUntil Quantity Cost
Address Price
Create one entry in the quote table, and then for each item on that quote create an entry in the QuoteItem table with the corresponding QuoteID.

DynamicQuery: How to select a column with linq query that takes parameters

We want to set up a directory of all the organizations working with us. They are incredibly diverse (government, embassy, private companies, and organizations depending on them ). So, I've resolved to create 2 tables. Table 1 will treat all the organizations equally, i.e. it'll collect all the basic information (name, address, phone number, etc.). Table 2 will establish the hierarchy among all the organizations. For instance, Program for illiterate adults depends on the National Institute for Social Security which depends on the Labor Ministry.
In the Hierarchy table, each column represents a level. So, for the example above, (i)Labor Ministry - Level1(column1), (ii)National Institute for Social Security - Level2(column2), (iii)Program for illiterate adults - Level3(column3).
To attach an organization to an hierarchy, the user needs to go level by level(i.e. column by column). So, there will be at least 3 situations:
If an adequate hierarchy exists for an organization(for instance, level1: US Embassy), that organization can be added (For instance, level2: USAID).--> US Embassy/USAID, and so on.
How about if one or more levels are missing? - then they need to be added
How about if the hierarchy need to be modified? -- not every thing need to be modified.
I do not have any choice but working by level (i.e. column by column). I does not make sense to have all the levels in one form as the user need to navigate hierarchies to find the right one to attach an organization.
Let's say, I have those queries in my repository (just that you get the idea).
Query1
var orgHierarchy = (from orgH in db.Hierarchy
select orgH.Level1).FirstOrDefault;
Query2
var orgHierarchy = (from orgH in db.Hierarchy
select orgH.Level2).FirstOrDefault;
Query3, Query4, etc.
The above queries are the same except for the property queried (level1, level2, level3, etc.)
Question: Is there a general way of writing the above queries in one? So that the user can track an hierarchy level by level to attach an organization.
In other words, not knowing in advance which column to query, I still need to be able to do so depending on some conditions. For instance, an organization X depends on Y. Knowing that Y is somewhere on the 3rd level, I'll go to the 4th level, linking X to Y.
I need to select (not manually) a column with only one query that takes parameters.
=======================
EDIT
As I just said to #Mark Byers, all I want is just to be able to query a column not knowing in advance which one. Check this out:
How about this
Public Hierarchy GetHierarchy(string name)
{
var myHierarchy = from hierarc in db.Hierarchy
where (hierarc.Level1 == name)
select hierarc;
retuen myHierarchy;
}
Above, the query depends on name which is a variable. It mighbe Planning Ministry, Embassy, Local Phone, etc.
Can I write the same query, but this time instead of looking to much a value in the DB, I impose my query to select a particular column.
var myVar = from orgH in db.Hierarchy
where (orgH.Level1 == "Government")
select orgH.where(level == myVariable);
return myVar;
I don't pretend that select orgH.where(level == myVariable) is even close to be valid. But that is what I want: to be able to select a column depending on a variable (i.e. the value is not known in advance like with name).
Thanks for helping
How about using DynamicQueryable?
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Your database is not normalized so you should start by changing the heirarchy table to, for example:
OrganizationId Parent
1 NULL
2 1
3 1
4 3
To query this you might need to use recursive queries. This is difficult (but not impossible) using LINQ, so you might instead prefer to create a parameterized stored procedure using a recursive CTE and put the query there.

Customized Auto-Number IDs for tables?

Is there a way to use my own number in a table like an auto-number; that is to automatically assign the next available to a new record. We have system ID numbers for each employee that I want to tie into this database. I just want the table to auto assign the next number.
Can I do this?
Could this be done with a mixture of numeric and alpha?
Could criteria be used, like Code A = certain set of numbers, Code B = another?
Of course you can, but you will have to design this yourself.
There are hundreds of ways of doing this but one way might be that you may have a parameters table with "nextQuote", "nextEmployeeNo", "nextJob"... of course your table design could have anything, including prefix example;
PARAMETERS
Prefix Number
Q 1145
E 54
J 999
So now you can SELECT PreFix + MAX(Number) AS NextEmployee FROM Parameters WHERE Prefix = E
And in your code you can increment the number after dealing with it.
UPDATE Parameters SET Number = number + 1 WHERE Prefix = E
If this isn't up to the job then hopefully it will get you thinking in how you can do something similar.
Hope this helps.
For ADO users:
How To Implement Multiuser Custom Counters in Jet 4.0
For DAO users:
How To Implement Multi-user Custom Counters in DAO 3.5