Database design for price data - php

I have a database that stores components in a component table.
There is a second table for component prices. This table has a field that maps to a component id. My price table needs to store information for a bunch of different prices (10, 100, 1000, 10K, 100K, 1M). The thing is, there is a possibility in the future to store other price types such as 25K or 50K.
As of right now, my price table looks like this:
id component_id type price
where the type can take values from 1-6 currently. This is good because it will allow me to add new price types in the future very easily.
The other option is a price table that looks like this:
id component_id price_10 price_100 price_1000 price_10K price_100K price_1M
But in this case, I would need to add a new field every time a new price type is added.
I hope that people here would agree with the first method.
But using the first method, I'm having trouble displaying a page that would display all my components in my database with the 6 prices it may or may not have (should show 0 in this case). Obviously this would be simple using the second method.
This is the query I have so far:
SELECT * FROM `component` LEFT JOIN `component_cost` ON `cmpcst_component` = `cmp_id`
EDIT:
I thought I would show some sample data from the component price table:
The prices are a unit price for an amount X. X ranges from 10 to 1 million. So I might have something like this in my component price table:
id component_id type price
1 1 1 0.50
2 1 2 0.45
3 1 3 0.40
4 1 4 0.35
5 1 5 0.32
6 1 6 0.30

The first option its much better.
For display the data, create a view with a pivot table.
You can found help here
http://en.wikibooks.org/wiki/MySQL/Pivot_table

Create two tables, one for components and one for compontent's prices (for a minimum count). Then you can add as many prices per component you would like. Now and in the future.
This is a variation of your first example, you just don't hardcode types but has the number that is related to a certain price.

Try something like:
select * from component c join compcst_component cc on true and c.id = cc.cmp_id;

I'm not sure I follow you.. Hope you can give us the table structures, but here's one try:
SELECT c.cmp_id, ISNULL(p.price, 0) AS Price
FROM component AS c INNER JOI component_cost AS p
ON p.cmpcst_component = c.cmp_id
Maybe I don't have the column-to-table matchup right, but try that.

Related

Search for synonyms in php sql database

I am searching for string in mysql database in php,which i m doing with like keyword.The problem is when i am having synonyms entered from user.Like in the database i m having all the products with the name shoes,and user enters footwear or some mismatched words.how to search for these different conditions..
Please guide on this.
Currently i m using following select query
Select * from table where name like '%user entered string%'
Please guide on how to tackle these conditions
Let's sum it up.
Let's assume that you have a table products which, I highly assume and hope, consists of products with unique ids.
products
id product
1 Shoes
2 Trousers
And so on. If you were to add an another column, let's say, synonyms, it would look something like this:
products
id product synonyms
1 Shoes Footwear, stuff on feet,
2 Trousers
We don't want this. You'd have to select the synonyms column, parse the string and make sure you don't ruin the column when you somehow wish to add new synonyms to each product.
It makes much more sense to have an atomic database where you'd have a table of synonyms where each synonym references a unique id in your products table, this way it's easy to delete old synonyms and add new ones.
products
id product
1 Shoes
2 Trousers
synonyms
id product_id synonym
1 1 Footwear
2 1 stuff on feet
You can then look up in this table if the original select like statement fails.
Using an external data-source is also a possibility but this is probably the most suitable way to go if you want to control the flow and avoid external sources.
For me, the best way is , add all match possibility keywords (shoes, footwear, men dress and etc.) to all products (to keywords column) when you add to base , which user will be search. And search products from this column(or table).

How to design database for tracking orders with set max items

I've got the following scenario:
In an order tracking system where sales reps track their orders:
Each order can have a total of 4 product types(commissionable buckets) and each bucket can 1 or none products of that product type.
So at max an order can have 4 products(one of each of the possible types)
The information I need to track for each of the four product types is the same: product-sold-id(fk), status, product-given-id(fk)
What would be the advantages of adding 12 columns to the order table: 3 for each product type like product-type1-sold-id, product-type1-status, product-type1-given-id..... Etc?
This would be easiest but my issue with this is that most orders would only have 2 or 3 product types sold which would result in 3 null fields per product type not sold. With 100 reps # 10 orders per day this would result in a lot of null fields.
I am leaning toward have an order items table with an order-id(fk) to cut down on all the null fields.
The issue with this approach would be that for one, I would have to add a level of complexity to either my client code to handle nested data, or my server code would have to flatten the data when requested and also be able to parse and save the flat data when sent modified from the client. Also with 100 reps#10 orders per day with 1-4 product types per order this would result in 1000-4000 rows added to the order items table per day. Is there any way of overcoming this?
Any advice would be appreciated. I am using extjs clientside, php serverside, with MySQL as my db.
Build a standard order data model, and put your application logic where it belongs, i.e. in the application layer (or maybe db sprocs).
What if your order maximum of 4 changes?
You should keep orders, products, and product types in their own tables. Then, you will use foreign keys to LEFT JOIN the tables together when returning results in PHP. This will allow you to scale the application with minimal effort. For example, adding up to five types to a product will require no changes to the database structure. Everything will be handled within the PHP code when limiting product types and products per order.
The foreign key is simply just a pointer to another table. For example, the table product_types should have a column named product_id for the primary key of the related product. The same works for products within an order. This is a very common way to represent one-to-many or many-to-many relationships.
For a code example, this is how you would return an order with the products.
SELECT * FROM products AS p
LEFT OUTER JOIN orders AS o ON o.id=p.order_id
WHERE o.id=1234;

Database design: implementing several types of the same entity

I'm coding a Classified Ads web application. The application has several types of Ads:
General ads(electronics, toys, pets, books...)
Real estate (houses, apartments, terrains...)
Vehicles (motocycles, cars, vans, trucks...)
Each type has several common fields (id, title, description) and also some that are exclusive to its kind:
General Ads (no exclusive fields)
Real estate (area, type-of-property...)
Vehicles (type-of-vehicle, cubic-capacity, kilometers...)
What is the most recommended approach to this situation?
A table that contains all fields and leave empty the fields that
don't apply to the current recordset.
A main table with the fields common to all Ads, and an additional table for each type of Ad that has exclusive fields.
One table for each type of Ad.
Other
I would build a solution depending on various criteria :
If you believe the table will be large in the future (a lot of ads to be published), you may want to minimize the number of JOINs for better performance => option 1. "one table with empty fields when not relevant to ad type"
Previous comment applies especially if your data storage cost is low.
If you have to query the data against certain field values (e.g. house size, car kilometers), you might avoid the solution described by phpalix (ad_type | property | value) or Andy Gee since your SQL syntax will be a nightmare, and prefer to have all your data in the same table (again).
If there are A LOT of custom fields per ad type, you might prefer to separate each ad type in their own table, for easier maintenance and data storage optimization. Then you can either JOIN or UNION to query your ads lists.
I'll add to my answer if i think of something else.
You can normalise (a table for the abstract concept and a table the the specialised one) or denormalise (a table with all the fields)
As always, the choice must be done according to the cost of each solution, reprensented by the speed of the queries (normalised model means more joins (buffer/cpu) whereas denormalised more disk reads usually because the columns are sometimes retrieved when it is not necessary) or the storage required in both cases.
All solutions are acceptable and a matter of preference, performance, complexity and design needs. The terms for what you are discussing are Table-Per-Type, Table-Per-Class and Table-Per-Hierarchy. If you google on these you are guaranteed to get a ton of Entity Framework results, but the underlying design considerations are much the same.
For flexibility I would have all the field in a separate table then allow the assigning of each field to each ad type. This would also allow you to add and remove fields easily at a later date.
Each field may have different types of data so this information should also be in a separate table.
Something like this (not very clear sorry)
Table: fields
field_id, field_type, field_name
1 1 title
2 1 price
3 2 size
4 3 description
5 1 square meters
Table: field_types
field_type_id, type
1, textbox
2, select_box
3, text_area
Table: field_data
field_data_id, ad_id, field_id, field_type_id, field_data
1 1 1 1 Cool t-shirt
2 1 2 1 5.99
3 1 3 2 L,XL,XXL,XXXL
4 1 4 3 Some description
5 2 1 1 Nice house
6 2 2 1 250000
7 2 4 3 Some description
8 2 5 1 1024sq/m
Table: ad_types
ad_type_id, ad_type_name, fields
1 general 1,2,3,4
2 real_estate 1,2,4,5
Well, store the values in columns and not in rows, so create a table and have 3 columns:
ad_type, property, value
define your properties for each type of ad and query the ad type for its fields.
Hope that helps

MySQL search in field (or other solutions)

I have a table with products that fall under specific categories, but the products within each category can contain multiple meta data tracking field
Table: products
id name category metadata
1 something 1 blue,red,purple
2 something else 2 left,right,middle
I have been trying to contemplate the best method to have a single product table but can't seem to squeeze the metadata in conveniently. for now I have created a table with all the metadata and fields for tracking the related category (the sequence is so i can order them withing a dropdown etc..)
Updated table: products
id name category metadata
1 something 1 1,2,3
2 something else 2 4,5,6
Table: metadata
id category sequence option
1 1 1 blue
2 1 2 red
3 1 3 purple
4 2 1 left
5 2 2 right
6 2 3 middle
If this format makes sense .. I am trying to generate a query that will search for values in my product table and grab each and all of the related meta values. The issue I am having is trying to find a unique value in the products field. if I do a MySQL search for LIKE(%1%) I will get matches for 1, 11, 21, 31 etc ... I thought of adding a leading and trailing comma to the field by default and then search for ",1," which would be unique .. but there has to be a better way ...
Any recommendations (regarding format or query)?
It's not an ideal design to have comma-separated values within a single database field. Aside from the problem you mentioned (difficult to search), your queries will be less efficient, as the DB won't be able to use indices for the lookup.
I'd recommend making a separate table products_metadata with a many-to-one relationship to the products table. Have the *metadata_id*, and the *product_id*, which is a foreign key linking back to the products table. That will make your job much easier.
You want to add another table, which links products to their metadata. It will have two columns: productid and metadataid which refer to the relevant entries in the products and metadata tables respectively. Then you no longer keep metadata in the products table, but JOIN them together as required.

How to tie products to categories?

The first time I tried to do this, I created a field in the category table called query. That contained strings like:
brand = "Burberry" AND type != "Watch"
Which I then inserted into the WHERE clause of a query to find a category's products.
That probably wasn't the best design.
My second attempt was to use a tagging system. I would create a tag table with tags like Burberry and Watch. I had a table tying the tags to the products (HABTM). I also had a table tying the tags to the categories.
The table tying tags to categories had an extra field called include which if it was a 1 then all products selected must also have that tag. Or if it was a 0 then all products selected must NOT have that tag.
This seemed to be a better design then my original, but it required some pretty complex joins.
Now I need to approach this problem once again.
One difference is I am now using the CakePHP (1.3) framework.
Before I try reinventing the wheel again. I was wondering if there are any known patterns/solutions I could use?
Probably you've already done that somehow by now, but here are my 2cents:
I'd drop Categories<->Tags, because I feel that you're unnecessarily duplicating data with it.
I.e. tables should be just categories, categories_products, products, products_tags and tags.
This way:
you wouldn't have to bother about changing category tags when products are added or removed from category
your searches would become more uniform (since there's only one tagging table)
and your tags still would be no more than 3 JOINS away - which is quite comfortable :)
From what I can understand you should have 5 tables:
Categories
Products
Tags
Categories_Tags
Products_Tags
UPDATE: When the user defines what should be selected, the HABTM tables are updated so that the tags/categories link to the products they should be linked to only.
So the query will look something like:
SELECT * FROM products WHERE ID in (SELECT product_id from tag list to include) AND ID NOT IN (select product_id FROM tag list to NOT include)
Maybe I'm missing what you're trying to accomplish here, but this sounds like you're making it more complicated than it needs to be.
Create three tables: Product, Category, and ProductCategory. Product and Category each have an id. Then ProductCategory includes ProductId / CategoryId pairs.
Like:
Product
ProductId Name
1 Lamp
2 Carpet
3 Drill
4 Power cord
5 3/8" bolt
Category
CategoryId Name
1 Electrical
2 Home decor
3 Hardware
ProductCategory
ProductId CategoryId
1 1
1 2
2 2
3 1
3 3
4 1
5 3
Then if you want, e.g., to know all the "Hardware" items:
select product.*
from category
join productcategory using (categoryid)
join product using (productid)
where category.name='Hardware'

Categories