Dynamically create MySQL table columns - php

I have the following MySQL table which is structured like that:
| id | bonus0 |
Now I want to add the following data set:
| id | bonus0 | bonus1 | bonus2 | bonus3 |
| 10 | 4582 | 2552 | 8945 | 7564 |
As you can see the columns bonus1 - bonus3 aren´t created yet.
How would a php script/ query look like which checks if enough columns are already available and if not which will create the missing ones with consecutive numbers at the end of the word "bonus"?
So in the example the columns bonus1 - bonus3 would be created automatically by the script.

In reality (I mean a normalized relational database) you should have 3 tables. Lets call them people, bonuses and bonus_to_person
people looks like:
+-----------------+------------+
| person_id | name |
+_________________+____________+
| 1 | john |
+-----------------+------------+
| 2 | frank |
+-----------------+------------+
bonuses Looks like
+----------------+--------------+
| bonus_id | amount |
+________________+______________+
| 1 | 1000 |
+----------------+--------------+
| 2 | 1150 |
+----------------+--------------+
| 3 | 1200 |
+----------------+--------------+
| 4 | 900 |
+----------------+--------------+
| 5 | 150 |
+----------------+--------------+
| 6 | 200 |
+----------------+--------------+
bonus_to_person Looks like
+----------------+-----------------+
| bonus_id | person_id |
+________________+_________________+
| 1 | 1 |
+----------------+-----------------+
| 2 | 2 |
+----------------+-----------------+
| 3 | 2 |
+----------------+-----------------+
| 4 | 1 |
+----------------+-----------------+
| 5 | 1 |
+----------------+-----------------+
| 6 | 1 |
+----------------+-----------------+
This way, any ONE person can have unlimited bonuses simply by INSERTING into bonuses with the amount, and INSERTING into bonus_to_person with the bonus_id and person_id
The retrieval of this data would look like
SELECT a.name, c.amount from people a
LEFT JOIN bonus_to_people b
ON a.person_id = b.person_id
LEFT JOIN bonuses c
ON c.bonus_id = b.bonus_id
WHERE a.person.id = 1;
Your result from something like this would look like
+------------+----+-------+
| name | amount |
+____________+____________+
| john | 1000 |
+------------+------------+
| john | 900 |
+------------+------------+
| john | 150 |
+------------+------------+
| john | 200 |
+------------+------------+
You should be using this normalized approach for any database that will continue growing -- Growing "deeper" than "wider" is better in your case ..

// Get existing columns of the table
// $queryResult = run SQL query using PDO/mysqli/your favorite thing: SHOW COLUMNS FROM `table`
// Specify wanted columns
$search = ['bonus0', 'bonus1', 'bonus2', 'bonus3'];
// Get just the field names from the resultset
$fields = array_column($queryResult, 'Field');
// Find what's missing
$missing = array_diff($search, $fields);
// Add missing columns to the table
foreach ($missing as $field) {
// Run SQL query: ALTER TABLE `table` ADD COLUMN $field INT
}

Related

Best way to populate table from multiple MySQL database tables

I'm building a student score viewing table using MySQL in the backend. So far, I have two tables for this feature. activities contains the class code it belongs into, it's own unique activity code, a name, the max score of the activity, and when it was added as a UNIX timestamp. outputs refers to students' outputs per activity, containing the activity code, the student code, and the score.
TABLE activities
+----+------------+---------------+---------------+-----------+------------+
| id | class_code | activity_code | activity_name | max_score | time_added |
+----+------------+---------------+---------------+-----------+------------+
| 1 | Pq5H | xJDM | Seatwork 1 | 10 | 1578632389 |
+----+------------+---------------+---------------+-----------+------------+
| 2 | Pq5H | JXrA | Seatowrk 2 | 15 | 1578952035 |
+----+------------+---------------+---------------+-----------+------------+
| 3 | JXrA | b5Ud | Seatwork 1 | 10 | 1578975406 |
+----+------------+---------------+---------------+-----------+------------+
TABLE outputs
outputs.activity_code references activities.activity_code
+----+---------------+--------------+-------+
| id | activity_code | student_code | score |
+----+---------------+--------------+-------+
| 1 | xJDM | FAb1 | 10 |
+----+---------------+--------------+-------+
| 2 | JXrA | FAb1 | 14 |
+----+---------------+--------------+-------+
| 3 | xJDM | jIPA | 8 |
+----+---------------+--------------+-------+
| 4 | JXrA | jIPA | 12 |
+----+---------------+--------------+-------+
| 5 | Pq5H | FAb1 | 9 |
+----+---------------+--------------+-------+
| 6 | Pq5H | jIPA | 7 |
+----+---------------+--------------+-------+
On the frontend, I also have an editable table where users edit the score like so:
FOR CLASS Pq5H
+---------+------------+------------+
| Student | Seatwork 1 | Seatwork 2 |
+---------+------------+------------+
| FAb1 | 10 | 14 |
+---------+------------+------------+
| jIPA | 8 | 12 |
+---------+------------+------------+
In short, the column headers contain the activities for a specific class, the first row contains the students in that class, and the cells are the scores of the students in the corresponding columns.
The users would also be able to dynamically add columns which creates new activities, and when they save, the new scores would be added to the outputs table.
What would be the best way to go around (1) populating the HTML table and (2) saving output data from new HTML columns into the database? So far, all I found regarding this are populating HTML table rows with rows directly lifted from the database, which is not what I need in this case.
I'm using HTML, JS (with jQuery), PHP, and MySQL.
Get the data using
SELECT student_code,
activity_name,
score
FROM activities
[LEFT] JOIN outputs USING (activity_code)
WHERE class_code = ?
[ORDER BY 1,2]
and PIVOT it on the client side.
Alternatively get
SELECT student_code,
CONCAT('{', GROUP_CONCAT(CONCAT('"', activity_name, '":"', score, '"') SEPARATOR ',') , '}') scores_in_json
FROM activities
JOIN outputs USING (activity_code)
GROUP BY student_code
WHERE class_code = ?
[ORDER BY 1,2]
and convert JSON to PIVOT on the client side.

Query mysql when reach row then stop? show the queue number

I am doing a script want to calculate how many row record before an user record when t1.status is 1.
My table is t1, and the data as below:
+------+---------+------------+----------+----------+
| ID | name | desc | status | time |
+------+---------+------------+----------+----------+
| 1 | ABB | | 1 | 0325 |
| 2 | CCD | | 1 | 0236 |
| 3 | EEF | | 1 | 0325 |
| 4 | GGG | | 1 | 0000 |
| 5 | HIJ | | 2 | 1234 |
| 6 | KKK | | 1 | 5151 |
+---------------------------------------------------+
I was thinking about the query is something like (query row where status = 1 AND stop when reach $userid)
I would like to output to show user (Let's say username is GGG) as:
$userid = 'GGG';
then my output will be
<table><tr><td>Queue: GGG You came in 4 place, in front of you still got 3 person in queue, please be patient</td></tr></table>
How to I do the right query to get the number 4 and 3 ?
Thank you.
You can try something like this hope it helps :-
SELECT count(*) as COUNT FROM t1 WHERE id < (SELECT id FROM t1 WHERE userid = $userid)

multiple or single selection

i have two tables and column name are as :
Table 1
user | food | color | bike | car
Table 2
user | mobile | laptop
Now i want to get result by select single or multiple value.
For example, if i want select user which have bike and laptop . then i can get result it by query but for this all fields i have to use many condition . i have used if else where. and i also want to refine select with current selection . so what should i use ? Please help my previous question was same but i did not asked perfectly. so asked again. Thank You.
You can use multiple tables in your single SQL query. The act of joining in MySQL refers to smashing two or more tables into a single table.
You can use JOINS in SELECT, UPDATE and DELETE statements to join MySQL tables.
Example
+-----------------+----------------+
| tutorial_author | tutorial_count |
+-----------------+----------------+
| mahran | 20 |
| mahnaz | NULL |
| Jen | NULL |
| Gill | 20 |
| John Poul | 1 |
| Sanjay | 1 |
+-----------------+----------------+
SELECT * from tutorials_tbl;
+-------------+----------------+-----------------+-----------------+
| tutorial_id | tutorial_title | tutorial_author | submission_date |
+-------------+----------------+-----------------+-----------------+
| 1 | Learn PHP | John Poul | 2007-05-24 |
| 2 | Learn MySQL | Abdul S | 2007-05-24 |
| 3 | JAVA Tutorial | Sanjay | 2007-05-06 |
+-------------+----------------+-----------------+-----------------+
SELECT a.tutorial_id, a.tutorial_author, b.tutorial_count
-> FROM tutorials_tbl a, tcount_tbl b
-> WHERE a.tutorial_author = b.tutorial_author;
+-------------+-----------------+----------------+
| tutorial_id | tutorial_author | tutorial_count |
+-------------+-----------------+----------------+
| 1 | John Poul | 1 |
| 3 | Sanjay | 1 |
+-------------+-----------------+----------------+
http://www.tutorialspoint.com/mysql/mysql-using-joins.htm

query specific table based on search keyword in mysql

I am creating a search portal in PHP from which user can search for a specific cuisine. In MySQL I have multiple tables for each cuisine and the respective hotel names that offer the cuisine. For example, in table
How can I query a specific cuisine table based on the cuisine search keyword?
So if a user enters 'mexican' as the search query, how can it connect to the 'Table2 - Mexican' and return the hotel names from this table?
Table1 - Chinese
_______________________
| id | hotelname |
|______|______________|
| 1 | hotel1 |
| 2 | hotel2 |
| 3 | hotel3 |
| 4 | hotel4 |
| 5 | hotel5 |
|______|______________|
Table2 - Mexican
_______________________
| id | hotelname |
|______|______________|
| 1 | hotel1 |
| 2 | hotel2 |
| 3 | hotel3 |
| 4 | hotel4 |
| 5 | hotel5 |
|______|______________|
Table3 - Pizza
_______________________
| id | hotelname |
|______|______________|
| 1 | hotel1 |
| 2 | hotel2 |
| 3 | hotel3 |
| 4 | hotel4 |
| 5 | hotel5 |
|______|______________|
Your database concept is very unflexible. I think you should put the cuisines into your database as information (i.e. table content) instead of metadata describing single tables. Tables should generally considered to be static just like the code you write to access the database and its tables. If you implement the cuisines as different tables you would have to hardwire every cuisine into your code.
Here is a suggestion for a better approach:
Create a hotels table to store all the hotels,
Create a cuisines table to store all the different types of cuisines,
Make an additional table to establish the n:m relationship between the hotel and the cuisine.
Example:
hotels: id, name, address, city, telno, email
cuisine: id, name, description
rel: cuisine, hotel (where both are the foreign keys to the
id columns of the respective tables above)
See also:
How to handle a Many-to-Many relationship with PHP and MySQL.
MySQL: Many To Many Relationships » Return True
You might want to check this question to create a many-to-many relationship:
many-to-many and many-to-many intersections
I guess what you would like to achieve is something like this:
Table1 - Hotel
_______________________
| id | hotelname |
|______|______________|
| 1 | hotel1 |
| 2 | hotel2 |
| 3 | hotel3 |
| 4 | hotel4 |
| 5 | hotel5 |
|______|______________|
Table2 - Cuisine
____________________________________________
| id | cuisine_name | keywords |
|______|______________|____________________|
| 1 | Chinese | Shandong,Noodles,. |
| 2 | Mexican | Tacos,Beans,... |
| 3 | Itarian | Pizza,Pasta,.. |
|______|______________|____________________|
Table3 - HotelCuisine
___________________________________
| id | hotel_id | cuisine_id |
|______|____________|______________
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
| 5 | 3 | 3 |
|______|____________|_____________|
SQL:
SELECT hotelname, cuisine_name FROM Hotel
INNER JOIN HotelCuisine ON Hotel.id = HotelCuisine.hotel_id
INNER JOIN Cuisine ON Cuisine.id = HotelCuisine.cuisine_id
WHERE keywords like '%pizza%'
Result:
________________________________________
| hotelname | cuisine_name |
|_______________|______________________|
| hotel1 | Itarian |
| hotel3 | Itarian |
|_______________|______________________|
DEMO: http://sqlfiddle.com/#!2/961de/1
Hope this helps
you can check SQL UNION. But instead of having multiple tables with the same fields, you can try normalization to minimize the redundancy and to make queries easier.
Something like:
Hotel Table
-----------------------------
id | hotelname | categoryID
------------------------------
1 | hotel name 1 | 1
2 | hotel name 2 | 2
-----------------------------
Category Table
-------------------
id | categoryname
-------------------
1 | chinese
2 | mexican
------------------
And query as simple as:
SELECT a.hotelname, b,categoryname
FROM hotel_table a
LEFT JOIN category_table b
ON a.categoryID = b.id AND b.categoryname LIKE '%mexican%';

How To Copy Database Records and Track Their New IDs

I have three tables: years, employees, positions. Suppose that I already have these data in those tables.
years:
----------------
| id | name |
----------------
| 1 | 2011 |
----------------
positions:
------------------------------
| id | name | year_id |
------------------------------
| 1 | Director | 1 |
| 2 | Manager | 1 |
------------------------------
employees:
---------------------------------------------------------
| id | name | position_id | year_id |
---------------------------------------------------------
| 1 | Employee A (Director) | 1 | 1 |
| 2 | Employee B (Manager) | 2 | 1 |
---------------------------------------------------------
========================================
The years table is a central point.
If I insert a new year record, I must also copy all positions and employees which are related to the previous year.
So if I insert year 2012 into the years table, the data is suppose to be like this:
years:
----------------
| id | name |
----------------
| 1 | 2011 |
| 2 | 2012 |
----------------
positions:
------------------------------
| id | name | year_id |
------------------------------
| 1 | Director | 1 |
| 2 | Manager | 1 |
| 3 | Director | 2 |
| 4 | Manager | 2 |
------------------------------
employees:
---------------------------------------------------------
| id | name | position_id | year_id |
---------------------------------------------------------
| 1 | Employee A (Director) | 1 | 1 |
| 2 | Employee B (Manager) | 2 | 1 |
| 3 | Employee A (Director) | 3 (?) | 2 |
| 4 | Employee B (Manager) | 4 (?) | 2 |
---------------------------------------------------------
NOTICE the question marks in the third and fourth row of employees table.
I use these queries to insert a new year and copy all related positions and employees:
// Insert new year record
INSERT INTO years (name) VALUES (2012);
// Get last inserted year ID
$inserted_year_id = .......... // skipped
// Copy positions
INSERT INTO positions (name, year_id) SELECT name, $inserted_year_id AS last_year_id FROM positions WHERE year_id = 1;
// Copy employees
INSERT INTO employees (name, position_id, year_id) SELECT name, position_id, $inserted_year_id AS last_year_id FROM employees WHERE year_id = 1;
The problem is at copying employees query. I can't find a method to get or track the new ID of positions.
Is there a simple method to do this?
Thank you very much.
Your data model is seriously flawed and probably needs a complete overhaul, but if you insist on copying the data like you describe, this should do the trick:
// Copy employees
INSERT INTO employees (name, position_id, year_id)
SELECT name, new_positions.id, $inserted_year_id AS last_year_id
FROM employees
JOIN positions AS old_positions ON old_positions.id = employees.position_id
AND old_positions.year_id = employees.year_id
JOIN positions AS new_positions ON new_positions.name = old_positions.name
AND new_positions.year_id = $inserted_year_id
WHERE employees.year_id = 1
I think you should read about database normalization. Copying the data leads to maintenance issues and erroneous reporting.
If you went with a different design like the following, then there would be nothing to insert, until an employee changes position, is terminated, or a position is discontinued. There are plenty of other ways to approach this, too, but you should minimize redundancy (i.e. have only one copy of each Employee), and then keep track of data that changes over time, separately. Also read about foreign keys before you try to implement something like this.
positions:
-- If you are keeping track of the years that each position is active,
-- using dates provides simplicity. Note: this design assumes that positions
-- are never reactivated after being deactivated.
------------------------------------------------
| id | name | DateActive | DateInactive |
------------------------------------------------
| 1 | Director | 01/01/2011 | |
| 2 | Manager | 01/01/2011 | |
------------------------------------------------
employees:
---------------------------------------------------------------
| id | name | DateHired | DateTerminated |
---------------------------------------------------------------
| 1 | Employee A | 01/01/2011 | |
| 2 | Employee B | 01/01/2011 | |
| 3 | Employee C | 01/01/2011 | 10/01/2012 |
---------------------------------------------------------------
EmployeePositionRelationships
--If you are keeping track of time that each employee held a position
-- Employee A has been a Director since 1/1/2011
-- Employee B was a Manager from 1/1/2011 to 10/6/2012. Then they became a Director
-- Employee B was a Manager from 1/1/2011 to 10/1/2012. Then they were terminated
--------------------------------------------------------
EmployeeId | PositionId | DateStarted | DateEnded |
--------------------------------------------------------
1 | 1 | 01/01/2011 | |
2 | 2 | 01/01/2011 | 10/6/2012 |
3 | 2 | 01/01/2011 | 10/1/2012 |
2 | 1 | 10/6/2012 | |
--------------------------------------------------------

Categories