SQL...updating product prices but keeping previous values - php

I have a table full of products including price, name, date and ID (PK)
I am in need to update the records when there is a price change (Web scraping script), how would i go about this so that a new row is NOT inserted, rather the price and date are updated.....but the previous values need to remain in the DB....so that when i when i go
"SELECT * FROM items WHERE id ='27'";
Output wanted:
$400 12.4.2013
$314 22.4.2013
$250 12.4.2013
The product will be then displayed with all the updated values since the first price was downloaded, effectively it will be a history of the prices for the item...
the actual results i want to achieve would hopefully be
History for "Product 27" is:
To give more context, when i run my script... ./script.php update
all the new data should be inserted or updated....but old values remain
im not too sure how i should approach this....please provide me with some guidance or assistance

The best way to go about this while keeping a tidy database with easily maintainable and readable data would be to take what #KishorSubedi said in the comment and create a log table.
When you update your price in your Products Table, store the old price, along with its date and ID in the Log Table then when you need to look up all the records for that product you can JOIN the Log Table in your query.
Log Table
| ProductID | Price | Date |
| 27 | $300 | 02.1.2013 |
| 27 | $400 | 03.1.2013 |
This way you can have a nice and neat Products table that is not cluttered with multiples of the same product, and an unobtrusive log table that is easily accessible.
Hope this gives you some guidance on building your site and database.

If you want to keep the old values I would suggest saving them in a seperate table and to use the INSERT statement. You are always adding a new row, so you can not bypass an insert or select into or similar statement.
Table structure:
Items
------------------------------
Id primarykey
Name
Price
------------------------------
Id primarykey autoincrement
ItemId index
AddDate index
Price
Now when you scrape the web you will just insert the new price in the Price table. If you want to select all the prices for an item you can use
SELECT Items.Id
,Items.Name
,Price.Price
,Price.AddDate
FROM Items
LEFT JOIN Price
ON Items.Id=Price.ItemId
WHERE Items.Id='27'
ORDER BY Items.Name ASC, Price.AddDate ASC
And if you just want the latest or current price, you can use
SELECT Items.Id
,Items.Name
,P1.Price
,P1.AddDate
FROM Items
LEFT JOIN Price P1
ON Items.Id=Price.ItemId
LEFT JOIN Price P2
ON P1.ItemId=P2.ItemId
AND P1.Id<P2.Id
WHERE Items.Id='27'
AND P2.Id IS NULL

Add new column for history in 'item' table and each price change append the changed value to this column with a specific format as like date1:price1,date2:price2,....

Related

Display the article in the database base on categories

I am having a database with a table to stock the products of my site and the table has the following column for all the categories a specific product belongs to:
After making a query to get the categories the first row belongs to, The information is stored in an object which looks like this $productDetails->ProductCategoryID and the content is the following: dinner,casual,kids
Now,my question is that how can I use the SQL command SELECT to get all the products having at least one category in common by using PHP.
Kindly help me solve this problem. Sorry I am not a native english speaker
If I've understood, you have a column which contains a string representing product's categories separated by comma. In this case you have to execute a substring function on the column ProductCategoryID, which is always discouraged.
I suggest you, instead of using the column ProductTable.ProductCategoryID, to make a link table ProductsCategories with the columns ProductID, CategoryID.
----------------------
| ProductsCategories |
----------------------
| ProductID |
| CategoryID |
----------------------
In this way you can use a more efficient QUERY like this one:
SELECT DISTINCT ProductTable.*
FROM ProductTable
INNER JOIN ProductsCategories ON (ProductsCategories.ProductID = ProductTable.ProductID)
WHERE CategoryID IN
(
SELECT CategoryID
FROM ProductsCategories
WHERE ProductID != ProductTable.ProductID
)
;
All this, of course, has sense if I've understood in the right way the structure of ProductCategoryID column :)

Multi Row/Column Table with PHP

I need to generate a HTML Table based on data which comes from MySQL Database. The Table is complicated so i will try to explain it here.
Data:
Article Name, Price, Date
Article1, 100.5, 2014-08-01
Article2, 90.0 , 2014-08-01
Article3, 80.0 , 2014-08-01
Article2, 90.0 , 2014-08-02
Article3, 80.0 , 2014-08-02
Article1, 100.5, 2014-08-03
Article3, 80.0 , 2014-08-03
This are the dataset which i get from Database. For everyday we get an entry of articles and their price. But it can be that an article is not available on a day. In such a case we need to set zero Price for this date. So now i have to build a horizontal table to compare the results. Some thing like this:
Screenshot
Can somebody tell me how I can generate such a table with PHP/HTML?
Your table is violating the first normal form because you have repeating data. Look here: Normal forms
A better way to create the database is to split your table into 2. First you have a table
Article
-----------
ID Article name
and a table
Price
----------------
ID fkArticle Price Date
the fkArticle is called a foreign key and is a link to the Article table. ID is a primary key and should be auto incremented. Both ID and fkArticle are the type 'int'
This is a lot better because you can avoid having a price of 0 if it the price doesn't exist. And you can extract all prices of an article like this
SELECT * FROM Price WHERE fkArticle = 1
This will get you all prices for an article with the ID=1
You can also easily get your first result by searching on date
SELECT * FROM Price INNER JOIN Article ON Article.ID=fkArticle WHERE Date="2014-08-01"
This is a much more flexible way to do it and is adhering to the Normalforms.

Check if an id exists in a table before adding it to another table

I'm doing a small thing like the like feature you see on facebook. So the way I'm doing it is like this. I have a table called products which contains products that people can like.
Like this (stripped down):
id | prodName | status (0=clear, 1=blocked)
----------------------------------------------------------
1 | Philips Food Processor | 0
2 | Le Sharp Knife | 0
3 | Ye Cool Fridge | 0
Then comes the `likes` table like this:
id | prodName | prodId | userId
--------------------------------------------
1 | Philips Food Processor | 1 | 1
2 | Le Sharp Knife | 2 | 1
3 | Ye Cool Fridge | 3 | 1
4 | Ye Cool Fridge | 3 | 2
I need to check, before adding to the likes table, if a product with that id actually actually exists in the products table and its status = 0. I currently do this with a lot of php code. What would be a good way to do this using sql? Is it possible? Using foreign keys or something like that?
I'm using innodb table type.
You can do a conditional insert. For product 6 and user 7:
insert into Likes
(prodName, prodId, userId)
select prodName
, id
, 7
from Products
where id = 6
and status = 0
If this inserts no rows, you know that the product did not exist with status 0.
If you just want to phrase the insert so it follows the rules, then you can use insert . . . select as follows:
insert into likes(prodId, userId)
select <prodid>, <userid>
from products p
where p.prodid = <prodid> and status = 0
I don't think MySQL supports "partial" foreign key constraints, where you can also include the requirement on the flag.
And, you shouldn't put the product name int he likes table. You should look it up in the products table.
The key element of trying to add something to the likes table that does not exist in the product table is the feedback to the user that lets them know they're doing it wrong. Any answer you determine on should not ignore the user feedback side of things - which is basically going to require your PHP code.
However, yes - there is a way to do it via foreign keys. You can index the prodid in the second table, and reference it as a foreign key to the first table.id. This means that if you try an insert and you get an error, there's a chance that the problem is that you're trying to add something without a match in the first table.
However, trying to determine precisely what the error is so you can determine the proper logic to respond to that error causes its own mass of php code, and is less easily transparent for future developers to maintain. I'd suggest a simple method in your Product object: isValid( id ) that returns true/false - so your 'check for this' code simply goes if( Product.isValid( prodId ) ){ Like.insert( userId, prodId ); }
But at the same time, I'd REALLY recommend a foreign key constraint along with the php code you're probably already using, just as insurance against your database becoming cluttered with unlinked rows. It's usually best to have multiple barriers against bad data.
Additionally ... is there a reason why you're storing the product names both in the product table AND in the likes table? I don't see why you'd need it in the likes table.
--Check to see if cleared product exist in products table
Select count(*) from products p where p.status = 0 and p.id = %IDVALUE
--Check if your user previous liked product
Select count(*) from products p, likes l where p.id = l.prodId and l.userId = %USERID
In your code you can execute the statements (replace %IDVALUE and %USERID with actual values) and check the return column to get the count and preform your custom logic.
Currently you require the prodId to populate the likes table, hence you need to lookup the data regardless of the contraint regarding blocked. Hence:
INSERT INTO likes (prodname, prodId, userId)
SELECT prodname, id, 123456
FROM products
WHERE prodname='Le Sharp Knife'
AND status=0;
(just substitute 123456 and 'Le Sharp Knife' for the parameters you need).
Yuo need to query database to check record,
for example you product id is 2 so your query would be something like
$query = select * from 'your-like-table' where 'prodId ' = 'ID';
then
if ( !mysql_query('your-db',$query)):
if you come under this condition then it's the time when you enter your like to database
endif;
hope it helps

Querying multiple tables in MySQL

I am trying to fetch data from multiple tables depending on what is selected in a dropdown menu. My dropdown menu consists of a list of ID's (001, 002, etc).
Once a user selects one of them, I am using AJAX to dynamically fetch data depending on what was selected. I was able to fetch a single value depending on what was selected but having problems when multiple tables are involved.
My tables are set up like this:
Inventory table:
inven_ID (primary)
cost
description
Order table:
order_ID(primary)
orderdesc
Sale table:
inven_ID
order_ID
quantity
primary(inven_ID,order_ID)
My query is as follows:
$QRY = "SELECT
inven_ID,
order_ID,
cost,
description
FROM
Inventory,
Order,
Sale
WHERE Inventory.inven_ID = Sale.inven_id
AND Sale.order_ID = Order.order_ID
AND Order.order_ID ='".$q."'";
The $q represents the value from the dropdown menu (which I checked is valid). I am getting the error Column 'inven_ID' in field list is ambiguous. Basically, when they select some order id from the drop down (say 001), it looks for order_ID in my Order table, and fetches the inven_ID/cost/description of that particular order ID.
Eg. if someone ordered parts xy, yz, xyz for cost 10,20,30.
Selecting 001 would bring up:
001 xy 10
001 yz 20
001 xyz 30
I think I am not joining tables properly since the error says its ambiguous.
Any help on this?
edit: yes that fixed the problem, quite obvious that I did not catch it.
In the column list of your select, you just need to specify which inven_ID you want to retrieve. For instance:
SELECT Inventory.inven_ID, ...
The error is pretty obvious. inven_ID is ambiguous because you have it in Sale and in Inventory. Use a specifier like Sale.inven_ID or Inventory.inven_ID.

Mysql insert current result and then insert new result

I have an ajax live table edit to change the price of my current product. What I want to do is insert the price before I change it and then insert the updated price. The reason being is because I want to show the change in the updated price. Example: current price is $54.00 and I change it to $57.00. I need to keep a log of price change throughout the day and show the price change of $3.00. How would I go about inserting the old price while the updated price gets inserted also. Thanks.
I suggest you make your price table like this
table price
-----------
id unsigned integer autoincrement primary key
article_id integer /*link to articletable*/
valid_from date
valid_until date
amount decimal(10,2) /*always use decimal for money*/
Then you can insert your new price using the following 4 queries.
/*hide changes from the rest of the world until we are done*/
START TRANSACTION
/*invalidate the latest existing price in the price table*/
UPDATE price
SET valid_until = DATESUB(CURDATE(),INTERVAL 1 DAY)
WHERE article_id = '100' ORDER BY valid_until DESC LIMIT 1
/*the order by selects the latest item, the limit does only 1 update*/
/*insert the new price*/
INSERT INTO PRICE (article_id, valid_from, valid_until, amount)
VALUES ('100', CURDATE(), DATEADD(CURDATE(),INTERVAL 100 YEAR), '99.95')
/*show changes to the rest of the world*/
COMMIT
You need the transaction or you risk the price table being out of sync. Set the tabletype to InnoDB on the price table.
Al your other tables can be MyISAM, just make sure the price table is InnoDB.
You can now select prices by using:
SELECT article.name
,price.amount as price_per_item
,purchase.qty as number_of_items
,price.amount * purchase.qty as amount
FROM purchase
INNER JOIN article ON (article.id = purchase.article_id)
INNER JOIN price ON (price.article_id = purchase.article_id)
AND (purchase.transactiondate BETWEEN price.valid_from and price.valid_until)
WHERE purchase.id = '458'
you can maintain to different fields for the two. Like old_value and new_value. At the end of the day you can tally the values and print the difference.

Categories