I'm very new to PHP. I'm building a companion webservice for an iPhone application I'm creating.
I have the following DB table that i've created which is filled with triggers.
The basic concept is that for a given currency when the price hits the trigger price I'm going to send a push notification.
Before I can generate the push notification I need an elegant way to validate each entry in this table against the current market price.
On initial thought I was thinking to select each trigger price and each currency and compare against the current market price I have in another variable.
Could anyone tell me the most elegant way to achieve what I'm trying to do? (compare the whole table against market price for various currencies)
Also if you have any php snippets that would be great,
Thanks,
John
Well if the app has a user logged in then you only need to check for the rows for that user, which isn't that bad.
However I would implement the database differently, have a separate currencies table like this:
id SERIAL
currency_name VARCHAR(10)
market_price FLOAT
Then change your main table so that target_price is a FLOAT as well (you could use int if you store the number of cents -- or equivalent -- instead of a dollar value, so 103 instead of 1.03). Finally change currency to be an int that references the other table
currency_id INTEGER
Then you probably want to add a foreign key constraint to the table:
FOREIGN KEY (currency_id)
REFERENCES currencies(id)
Now you can update the currencies table as the market_price changes then use SQL to get a list of the rows that need triggered:
SELECT u.id
FROM users u, currencies c
WHERE u.currency_id = c.id
AND u.trigger_price <= c.market_price
;
That's probably the best way, in my opinion.
If you really need to do it in PHP then I'd create an associative array of the market prices where prices['currency_name'] = market price for that currency. And currency name matches the string in the table. Then you're just going to have to go through the whole table and check each match, assuming you've already fetched the table into $result and checked for errors:
while ($row = $result->fetch_assoc()) {
if (isset($prices[$row->currency) // Sanity check on the prices array
&& ($row->trigger_price <= $prices[$row->currency]))
{
// Matching row, do something with it ...
}
}
If you trust the database to only contain stuff in the currency array you can skip the sanity check. If you only want to check certain currencies you could only select rows that match currencies you have updates for.
I'm also assuming your condition is the trigger price being lower than the current price, you may need to do different logic depending on exactly what you want to do.
Related
What is the best way to create a unique identifier for an array of UUIDs?
I have a Product that consists of multiple components, each component has an UUID assigned to it.
When creating a new Product with it's components, I need to know if there is already another product having exactly the same components. I think going through MySQL, loading each product with it's components and checking them one by one will be time consuming.
This is my idea:
products table
--------------
id, name, components_uuid_hash
product_components table
------------------------
product_id, component_id, ...
components table
----------------
id, uuid, name, ...
I would calculate the components_uuid_hash:
$product_component_uuids = ['227A0140-F0FB-4FDA-B780-85152AB02927', 'FA0E6D52-F0E4-4F55-87F5-8D73625AEDA3'];
sort($product_component_uuids);
$component_uuid_hash = md5(serialize($product_component_uuids));
I would do this for each product, giving me a unique hash of the whole UUID array that I could simply lookup in the Products table to know if there has already been a different product with the same hash.
Can someone please confirm if this would work or if there is a different better approach?
Assuming you already have a list of uuids you can try to do it in MySQL with something like
select pc.product_id, count(c.id) as co from
product_components pc left join components c on (
pc.component_id=c.id and
c.uuid in ('227A0140-F0FB-4FDA-B780-85152AB02927', 'FA0E6D52-F0E4-4F55-87F5-8D73625AEDA3')
)
group by pc.product_id having co=2;
This will return all products that have exactly two components with UUIDs matching those in the list.
You need to adjust the count value at the end to match the number of uuids.
This will still do a full scan on the product_components table and will probably use a temporary table, so your plan to keep a hash of the UUIDs in the products table and search by it will probably be faster from a MySQL point of view, but you will have to update it every time a product or a component changes.
currently I found myself wondering if this is the right thing to do in this case.
You see I have a database called for example Warehouse
I this database I have two tables:
[the table items is for saving the items of the system add-modify-delete records]
Items (which its columns are )
TAG_ID
P_NUMBER
QUANTITY
TYPE
LOCATION
DESCRIPTION
REASON
USERID
DATE
[the table lastchanges is for saving the items of the system that has been changed]
lastchanges (which its columns are )
ID
TAGID
PNUMBER
USERID
ACTION
DATING
Now I have been asked to add "exactly what has been changed" to the current form, for example if the quantity changed I have to show that before and after in a bootstrap form.
My brain told me to just add all the columns of the table items into lastchanges and save on those columns the data before changing and into items the new modified data, but performance-wise I see this as a bad action and I want your opinion.
If I understand you correctly you need a history of your DB changes.
If thats the point I would recommend you to create a new row for each entry and soft delete the old one. Then nothing gets lost and you can always get differences or older values.
Adding a the field deleted_at, and created_at as dates would do that trick for you. If deleted_at is null its the current entry, if there is a date set you know exactly when it got "overwritten"
In a table for a users billing subscription info, there is the need for a field that states how often they are billed. Currently the only options are monthly or annually.
What is best practice in this case? Keep the actual value in a field of the subscription table or create a subscription frequency table, have annually be 1, and monthly be 2, and insert the ID into the subscriptions table?
With the specification, as given, with no other information...
My personal preference would be to just store the "subscription frequency" attribute in the entity table.
No need to create a separate table. (I don't see "subscription frequency" as being an entity in the system, and I've already got enough complexity with referential integrity and foreign keys for stuff I really need it for.)
I don't every query against my table to require a join to the "lookup" table to return a string value, out of an id. That just seems unnecessary.
Personally, I'd consider adding a column like this:
subscription_frequency ENUM('','monthly','annually')
If I need to add another value to the list:
ALTER TABLE mytable
MODIFY subscription_frequency ENUM('','monthly','annually','quarterly')
The ENUM examples here require only a single byte of storage. And the INSERT/UPDATE/SELECT statements with the ENUM work as if it was a VARCHAR, with some funkiness with INSERT/UPDATE of string values that aren't in the enum list.
If there's reasons to avoid ENUM, then I would just store the VARCHAR.
If I needed the extra lookup table, I wouldn't use a surrogate id as the primary key. I would use the string value 'monthly', 'annually' as the primary key, and the foreign key column. (I want to avoid requiring a JOIN to return a string from an id.) If there's an order to the values in the list, I'd add a sequence column to order them.
The billing-frequency is just an attribute of the subscription. And there is only one such attribute per subscription. So in my opinion there is no need for an extra table and join.
You could, of course, add an extra table with possible billing frequencies. Like 1: annually, 2: monthly, 3: weekly or whatever. And using that id as value in the billing-frequency-field of your subscription table.
Alternatively, you could store the amount of billing processes per year in that field and make the "naming" in your application. (1 = annually, 12 = monthly, 52 = weekly and so on).
This comes down to preference and expand-ability. I would personally create another table called something like SubscriptionFrequency with attributes id,description,billingFrequency,createDate,lastModifiedBy,etc... or something to that effect. The value you store in your UserBillingSubscriptionInfo could be a foreign key to this new table's primary key. If you do the other option (simply imply 1 = annual and 2 = monthly) I'd add descriptions to the schema or document somewhere how that relation works.
I have a table named orders_products which hold all the products associated with each individual orders. Now, if the customer decides to edit the quantity, the attributes, or simply just remove a product, what would be the easiest way to handle this change in the database?
orders_products
id | quantity | fk_products_id | attributes | price | fk_orders_nr
fk_products_id refers to the actual product id in our products table
attributes is a comma sepparated string with id's refering to our attributes table (attributes can be the angle, lenght, diameter etc. for each product. As in 45 degres, left angeled, 20 cm in length, 43mm in diameter).
fk_orders_nr is the actual order the product belongs to.
Since I have a class that handles this part on the client side. Would it be easier to just DELETE all associated products, based on the order id (fk_orders_nr), and just re-insert and updated the whole set based on what's stored in the class?
Or is there a neat way to handle this directly in MySQL?
I've looked a bit into on duplicate key update, and ignore, but they doesn't seem to fit my needs..
I need to check to see if the actual product id exists, then decide to insert new, or update existing (it could be both the quantity, and/or optional attributes), also the product might be removed if not in the list from the class anymore.
When writing this question. I think deleting the whole set, and reinsert it, might be the easiest way.
This database looks badly designed. Firstly I assume by fk_products_id you mean product_id. You do not need to specify that a column is a foreign key in its name.
Secondly, I would advise you to keep all columns atomic, as in, no multi-values. The attributes column keeping a comma-separated list will give you headaches in the future and it also breaks the FIRST normal form (the most basic one).
Thirdly, you don't need (although it could sometimes be useful) an id as a primary key in your junction table. You can just use a compound primary key from your fk_products_id and fk_orders_nr keys.
When writing this question. I think deleting the whole set, and
reinsert it, might be the easiest way.
Yes, that is the way it's usually done.
But I insist you ignore everything about the current problem you're having and redesign your database from scratch, putting special attention into normalization. These are basic database design standards and they exist for a reason. Hopefully you won't learn about the reason when it's too late.
I have a software in PHP and postgres that I use for invoicing. I am running a stock management system that I created. i am trying to create a stock movement page where I can see when a part came in, where it was issued and when and also when it was credited (if it was). I am running 5 tables for the stock. My main one is part2vendor, parts, expenses, wo_parts and int_part_issue. When I receive stock, it goes into the table part2vendor (onhand gets increased by number received). The expense table gets the details of the part number, the supplier invoice and the date received. wo_parts stores the part number issued to a workorder. int_part_issue is when I do a stock adjustment or use a part internally. I am looking to create a PHP table that would list (in date order) the 'paper trail' of a part. I can let you know table names and columns if required. Thanks.
Sounds like you need a simple history table?
Columns
part_history
id
part_id
date_modified (timestamp)
action ( or maybe action_id if you have an actions table)
vendor_id
And when you get a new part, and add it to the parts2vendor table ( i think u said) you would use the inserted part ID (or unique part id ) to add a record rto history
INSERT
(id, part_id, action, vendor_id)
46565, 5757575, "Purchased", 757575
The date will be inserted as a timestamp by postgres
Than for any part yuou can grab history relying on the uniquer id
sort by date_modified DESC.