Select a option from a database based on different variables? - php

I am looking to make PHP code that selects the best option in a data table. What is considered "best" would be based off of the variables/columns. I understand that I would need to start a mysqli query and create a couple of loops to search through the database, but I am not entirely sure how to implement something like this.
To give a more in-depth explanation of what I am talking about, here as an example.
(START EXAMPLE)
Lets say I have a database and there is a table with items in it. There are 3 columns: Item ID, Type, On Sale. I want to make it so that a user is able to pick out the best option based on those variables. In addition to finding the "best" option, it selects the one that is first listed in that order (in this case lowest Item ID).
Imagine this table:
Item ID | Type | On Sale
---------------------
1 | Chair | 0
2 | Table | 1
3 | Chair | 1
4 | Oven | 0
5 | Table | 1
6 | Oven | 0
The level of important goes like Type>On Sale>Item ID (lowest).
A user is looking for a chair. Item 3 is selected because it is his item and it is the first one also on sale.
A user is looking for a table. Item 2 is selected over Item 5 because it is listed higher (or in this case, has a lower Item ID)
A user is looking for an oven. Item 4 is selected because no ovens are on sale. Because no options are on sale, it selects the lowest Item ID of the ovens listed.
(END EXAMPLE)
So how should I go about this? Any answers would be greatly appreciated!

select * from table_name where Type = type_specified_by_user order by On Sale, Item ID

Related

How to synchronize cell values in the same table?

Big problem...
I'm implementing an online ticket sale system in PHP and MySQL. I have a table called "block_of_tickets", or something like that...
This table looks like:
+-----------+------------+--------------+--------------+--------------+
| idblock | block_name | total_tickets| block_gender | idblock_pair |
+-----------+------------+--------------+--------------+--------------+
| 1 | Block 1- M | 100 | MALE | 2 |
+-----------+------------+--------------+--------------+--------------+
| 2 | Block 1- F | 100 | FEMALE | 1 |
+-----------+------------+--------------+--------------+--------------+
Where:
idblock: The id (primary key) of the block of tickets.
block_name: The name of the block. In the example I have a "Block 1- M" and "Block 1- F" to represente the "Block 1 - Male" and "Block 1 - Female", respectively.
total_tickets: the total of available tickets
block_gender: the gender of the block of tickets
idblock_pair: the block wich is pair of the current block.
Note: There are also other columns, like "price", etc.
Here is the (big) problem:
When there is a "idblock_pair", it means that both block of tickets will share the same total_tickets (available tickets), so both cells must have exactly the same value in this case. As you can see in the example above, block 1 points to block 2 and vice-versa.
Lots of people buy lots of tickets in (almost) the same time, wich means that each sold ticket must decrement 1 in the "total_tickets" field, for both cells.
Database Normalization can solve this. However, it would lose a lot in performance.
I'm almost sure that I should use "SELECT... FOR UPDATE"... but I don't know how, since it's the same table, and a "deadlock" can occur...
How to solve this problem? Do I have to use Triggers? Proccedures? Do I have to use the PHP processing (and transactions) to solve this?
In the example below, one ticket were sold, and now I'm decrementing the total_tickets by 1:
START TRANSACTION;
SELECT *
FROM block_of_tickets
WHERE idblock in (1,2) FOR UPDATE;
UPDATE block_of_tickets
SET total_tickets = (total_tickets - 1)
WHERE idblock in (1,2);
COMMIT;
Is this a nice solution?

How to compare SQL rows based on values and obtain a sum?

I am attempting to upgrade an Old Custom eCommerce system. I am trying to make a log of quantity changes made to an item based on rows from a table (call it "old_table") that the old custom system creates. I can't seem to be able to crack this problem.
As someone starts to make a change to an Item in the system, it creates a record in the "old_table" with the values:
Time | User | Current Qty | Status | Item
-----------------------------------------------------------
2015-07-09 05:30:47 | Admin | 10 | Start | ABC 1
When the person finishes changing the quantity for an Item in the system, it creates a record in the "old_table" with the values:
Time | User | Current Qty | Status | Item
-----------------------------------------------------------
2015-07-09 05:50:47 | Admin | 09 | End | ABC 1
--- Note: Sadly, if the quantity is set to "00" there will not be an "End" entry. I have guessed that i would set a 24 hour limit then would consider that user to have set it to "00" ---
My Goal
In a new Table, I am trying to create a row stating that the User "Admin" subtracted/added a total of "X" of the Item "ABC 1" and if within 24 hours there is no "End" row within the "old_table" for the given item to make a row stating that the User "Admin" set the value to "00".
Anyone have Ideas, suggestions or a solution? I have tried for weeks to solve this. Is it not possible?
You tagged this with mysql AND sql-server. Which system/version is the one in use?
With SQL-Server (>=2008) you could use window function (OVER clause: https://msdn.microsoft.com/en-us/library/ms189461.aspx) which gives you grouped count, sum, avg and other aggregate function.

Create attributes from the admin panel

I am asked to give a possibility to the administrator of the site to create attributes in the database tables. There are sellers and buyers on the website, and each seller when adding a certain product, fills out the needed fields for the specific product, and then publishes the product. I am kind of confused on how is this going to work. If every product has specific fields, then that would mean that if the site has 2.000 products, I will have 2.000 tables? I've never worked on such thing, so I really don't know how to handle this. Furthermore, on the admin feature to create attributes. Let's say the product is a tomato. The admin adds field for the tomatoes that is called "condition" and it has options such as "frozen", and "fresh". Then, when some of the sellers tries to create tomato product, they will need to choose if the tomato's condition is fresh or frozen. I thought of a possible solution such as creating a table that will hold the text of the , and then another table that will hold the text of the .
product_tomato ( product_id, user_id, name, description, condition)
product_select( select_id, product_id, select_text)
product_option( option_id, select_id, option_text)
So, this is how I imagined the tables for doing this. So, when the admin adds a field to the product table, I will add a column in the product table, then create new row in the prodcut_select table, and then list the possible options in the product_option table. But then I got confused on how to display that on the product page. How am I going to deal with that in the code, when I don't know what are the names of the columns that the admin created?
The wording of the question is very confusing, but I believe I get the gist of what you're saying.
No, you would not make a table for every single product, that would get ridiculous very quickly. You can handle this easily for multiple products with three tables.
Tables:
Product
Product_Attributes
Seller_Product
Let's take your hypothetical example of a tomato with conditions.
The admin decides that his site will now offer tomatoes as a product. He creates a product, and adds it to the product table. Then, he decides that tomatoes should have a "condition" attribute that has two possible values, fresh and frozen. Therefore, he would add two rows to the Product_Attributes table, with three fields (Product, Condition, Value).
Therefore, your tables would now look like this.
Product Table:
*Name |*
Tomato
Product_Attribute Table:
*Product | Attribute | Value*
Tomato | Condition | Fresh
Tomato | Condition | Frozen
Finally, when your sellers added items to the site store or whatever it is, you would have them enter the data into a form that grabbed the conditions and potential values from the Product_Attribute table for that product. In this case, there's only one attribute so they would just fill out the condition. Let's assume that there are two sellers, Jim and Tom, who sell fresh and frozen tomatoes respectively. The final three tables would look like this.
Product Table:
*Name |*
Tomato
Product_Attribute Table:
*Product | Attribute | Value*
Tomato | Condition | Fresh
Tomato | Condition | Frozen
Seller Product Table:
*Seller | Product| Attribute | Value*
Jim | Tomato | Condition | Fresh
Tom | Tomato | Condition | Frozen
This way, you could store a variety of custom fields about products using three tables. You should normalize or denormalize as needed, you may want a table for seller's products only and store their conditions in a separate table. Either way, the method described above would get the job done.
I believe here's a good scheme:
product_data - product ID, category ID, name, price, description
product_meta - product ID, attribute_name, attribute_value
product_variants - product ID, variant ID, variant value
You'd also like separate tables for variant names and category names/descriptions.
Example:
ID | Category_ID | Name | Price
251 | 14 | Tomato | 5.00
ID | Attribute | Value
251 | Condition | Fresh
251 | Color | Red
ID | Variant_ID | Name | Value
251 | 50 | Size | Small
251 | 50 | Size | Huge
So basically you'll have around 5-10 tables (Google 3 steps of DB normalization). All tables are linked together by IDs.
All you'll need to do - retrieve the values using JOIN statement and WHERE product_id condition.

Conditionally Update Several Records Across Tables Based On Value Of A Column's Value For Each Row

I'm trying to streamline updating database records. I've investigated several methods and options but any that focus on PHP instead of MySQL would require hundreds if not thousands of queries, that is clearly not desirable. I'm working with three tables, one contains rows that identify various aspects of a product, one that connects the descriptive values to products and finally the products. The descriptive table has a column that is to trigger an update for all products that use it. The trouble I'm having is that the update might require the product use a new description and that description might have to be created and then set in the product connect table. The description table is also used to calculate the new value based off of another entry.
Description Table:
id | unit | type | update
------------------------------------
1 4oz weight
2 3 servings 1
3 7oz weight
4 4 servings
5 0.66 price_per_serving
6 0.49 price_per_oz
Connector Table:
id | description_id | product_id
--------------------------------
1 1 1
2 2 1
3 2 2
4 4 3
Product Table:
id | name | price
-----------------------
1 soup 1.99
2 crackers 2.00
3 chips 0.79
4 candy bar 0.99
So from the example tables I need to find that item 2 in the description table needs updating. Through the connector table I see the soup and crackers have three servings. I need to take the price of each item using entry 2 and divide it by the number of servings. If that new value isn't in the description table (say 0.78 price_per_serving), it needs to be created and the connector table needs to hold the id of the existing matching entry if one exists or the new one that was created if it didn't. The entry update field will now be cleared.
I can perform all of the functions with PHP no problem, as you can see though it would just place an enormous burden on resources.
I've been trying to wrap my head around sub-queries and reading plenty of articles, manuals and other questions on this site but I'm just so overwhelmed I don't know how to get started. I've found queries like the example shown in this post (http://stackoverflow.com/questions/2542571/mysql-case-when-then-returning-wrong-data-type-blob) but my MySQL experience is mostly select, update, insert.

Database Normalisation and Data Entry (admin backend)

Take a look at the items table below, as you can see this table is not normalized. Name should in a separate table to normalize it.
mysql> select * from items;
+---------+--------+-----------+------+
| item_id | cat_id | name | cost |
+---------+--------+-----------+------+
| 1 | 102 | Mushroom | 5.00 |
| 2 | 2 | Mushroom | 5.40 |
| 3 | 173 | Pepperoni | 4.00 |
| 4 | 109 | Chips | 1.00 |
| 5 | 35 | Chips | 1.00 |
+---------+--------+-----------+------+
This table is not normalize because on the backend Admin site, staff simply select a category and type in the item name to add data quickly. It is very quick. There are hundreds of same item name but the cost is not always the same.
If I do normalize this table to something like this:
mysql> select * from items;
+---------+--------+--------------+------+
| item_id | cat_id | item_name_id | cost |
+---------+--------+--------------+------+
| 1 | 102 | 1 | 5.00 |
| 2 | 2 | 1 | 5.40 |
| 3 | 173 | 2 | 4.00 |
| 4 | 109 | 3 | 1.00 |
| 5 | 35 | 3 | 1.00 |
+---------+--------+--------------+------+
mysql> select * from item_name;
+--------------+-----------+
| item_name_id | name |
+--------------+-----------+
| 1 | Mushroom |
| 2 | Pepperoni |
| 3 | Chips |
+--------------+-----------+
Now how can I add item (data) on the admin backend (data entry point of view) because this table has been normalized? I don't want like a dropdown to select item name - there will be thousands of different item name - it will take a lot of of time to find the item name and then type in the cost.
There need to be a way to add item/data quick as possible. What is the solution to this? I have developed backend in PHP.
Also what is the solution for editing the item name? Staff might rename the item name completely for example: Fish Kebab to Chicken Kebab and that will effect all the categories without realising it. There will be some spelling mistake that may need correcting like F1sh Kebab which should be Fish Kebab (This is useful when the tables are normalized and I will see item name updated every categories).
I don't want like a dropdown to select item name - there will be thousands of different item name - it will take a lot of of time to find the item name and then type in the cost.
There are options for selecting existing items other than drop down boxes. You could use autocompletion, and only accept known values. I just want to be clear there are UI friendly ways to achieve your goals.
As for whether to do so or not, that is up to you. If the product names are varied slightly, is that a problem? Can small data integrity issues like this be corrected with batch jobs or similar if they are a problem?
Decide what your data should look like first, based on the design of your system. Worry about the best way to structure a UI after you've made that decision. Like I said, there are usable ways to design UI regardless of your data structuring.
I think you are good to go with your current design, for you name is the product name and not the category name, you probably want to avoid cases where renaming a single product would rename too many of them at once.
Normalization is a good thing but you have to measure it against your specific needs and in this case I really would not add an extra table item_name as you shown above.
just my two cents :)
What are the dependencies supposed to be represented by your table? What are the keys? Based on what you've said I don't see how your second design is any more normalized that your first.
Presumably the determinants of "name" in the first design are the same as the determinants of "item_name_id" in the second? If so then moving name to another table won't make any difference to the normal forms satisified by your items table.
User interface design has nothing to do with database design. You cannot let the UI drive the database design and expect sensible results.
You need to validate the data and check for existence prior to adding it to see if it's a new value.
$value = $_POST['userSubmittedValue']
//make sure you sanitize the variable (never trust user input)
$query = SELECT item_name_id
FROM item_name
WHERE name='$value';
$result = mysql_query($query);
$row = mysql_fetch_row($result);
if(!empty($row))
{
//add the record with the id from $row['item_name_id'] to items table
}
else
{
//this will be a new value so run queries to add the new value to both items and item_name tables
}
There need to be a way to add item/data quick as possible. What is the
solution to this? I have developed backend in PHP.
User interface issues and database structure are separate issues. For a given database structure, there are usually several user-friendly ways to present and change the data. Data integrity comes from the database. The user interface just needs to know where to find unique values. The programmer decides how to use those unique values. You might use a drop-down list, pop up a search form, use autocomplete, compare what the user types to the elements in an array, or query the database to see whether the value already exists.
From your description, it sounds like you had a very quick way to add data in the first place: "staff simply select a category and type in the item name to add data quickly". (Replacing "mushroom" with '1' doesn't have anything to do with normalization.)
Also what is the solution for editing the item name? Staff might
rename the item name completely for example: Fish Kebab to Chicken
Kebab and that will effect all the categories without realising it.
You've allowed the wrong person to edit item names. Seriously.
This kind of issue arises in every database application. Allow only someone trained and trustworthy to make these kinds of changes. (See your dbms docs for GRANT and REVOKE. Also take a look at ON UPDATE RESTRICT.)
In our production database at work, I can insert new states (for the United States), and I can change existing state names to whatever I want. But if I changed "Alabama" to "Kyrgyzstan", I'd get fired. Because I'm supposed to know better than to do stuff like that.
But even though I'm the administrator, I can't edit a San Francisco address and change its ZIP code to '71601'. The database "knows" that '71601' isn't a valid ZIP code for San Francisco. Maybe you can add a table or two to your database, too. I can't tell from your description whether something like that would help you.
On systems where I'm not the administrator, I'd expect to have no permissions to insert rows into the table of states. In other tables, I might have permission to insert rows, but not to update or delete them.
There will be some spelling mistake that may need correcting like F1sh
Kebab which should be Fish Kebab
The lesson is the same. Some people should be allowed to update items.name, and some people should not. Revoke permissions, restrict cascading updates, increase data integrity using more tables, or increase training.

Categories