Increasing column number value based on another column - php

I have a table code with the following table structure. id is auto incrementing id, the code is a random unique 15 digit code and customer_id is the customer's id.
id code customer_id
1 123...4 1
2 124...5 1
3 128...3 1
4 234...1 2
5 678...3 2
6 567...8 1
The code is actually a 15 digit number which I am generating randomly as per below code. Based on the user input for the number of codes I generate the codes at once, insert ignore into the table and count post addition to the table if few lines were ignored due to duplicates and add the additional ones needed to make the total count needed by the user. I use this approach because the request for the number of codes is usually around 50k to 100k and this approach works well.
do{
$codes = array();
$question_marks = array();
$sql = "SELECT count(*) FROM code";
$stmt = $this->db->prepare($sql);
$stmt->execute();
$initialCount = $stmt->fetchColumn();
for ($i=0;$i<$codesToGenerate;$i++){
$code = getToken(15);
array_push($codesArray, $code, $customerId);
$question_marks[] = '(' . placeholders('?', 2) . ')';
}
$datafields = "code, customer_id";
$this->db->beginTransaction(); // also helps speed up your inserts.
$sql = "INSERT IGNORE INTO code (" . $datafields . ") VALUES " . implode(',', $question_marks) ;
$stmt = $this->db->prepare($sql);
try {
$stmt->execute($codesArray);
}catch (\PDOException $e){
echo $e->getMessage();
$result = 0;
}
$this->db->commit();
$sql = "SELECT count(*) FROM code";
$stmt = $this->db->prepare($sql);
$stmt->execute();
$finalCount = $stmt->fetchColumn();
$rowsInserted = $finalCount - $initialCount;
$codesGenerated += $rowsInserted;
$codesToGenerate = $codesToGenerate - $rowsInserted;
}while($codesToGenerate>0);
I have added a column serial_number in table and I want to add a serial_number which will increment for each value of respective customer like below based on the customer_id. How do I change PHP code to add serial_number as well. Please note that I want to avoid holes in serial_number.
id code customer_id serial_number
1 123...4 1 1
2 124...5 1 2
3 128...3 1 3
4 234...1 2 1
5 678...3 2 2
6 567...8 1 4
How do I do this?
Below are some of my thoughts:
1)Should it be done seperately post this transaction?
2)Should I maintain a last count of serial_number for each customer in a separate table and then increment in PHP before adding to table.
3) How do I take care of concurrencies if I use the approach mentioned in 2 above

Related

Clone / Insert multiple linked tables in PHP PDO and MySQL

I have three tables linked through ID's which I would like to clone / duplicate on button click.
The new rows would be assigned new ID's through Auto Increment.
// Table One
**quote_id (PRIMARY)**
customer
quote_contact
enquirey
quote_name
quote_date
quote_status
// Table Two
**quote_details_id (PRIMARY) **
*quote_id (FOREIGN)*
quote_details_desc
quote_details_quantity
// Table Three
**qd_item_id (PRIMARY)**
*qd_quote_details_id (FOREIGN)*
qd_item_cat_id,
qd_item_desc_id,
qd_item_notes,
qd_item_quantity,
qd_item_cost,
qd_item_markup,
qd_item_total
So far, I have been able to copy / clone the first two tables successfully, however the third is a little tricky.
I need to find each inserted ID from table two, and duplicate / clone the records in table three. How would be best to go about this? I assume I need some sort of way of looping through each ID from table two, to insert the data by each ID?
Below is my working code for the first two table inserts:
$version = $_POST["btn_click_row_id"];
$query = "
INSERT INTO quotes (customer, quote_contact, enquirey, quote_name, quote_date, quote_status)
SELECT customer, quote_contact, enquirey, quote_name, quote_date, quote_status
FROM quotes
WHERE quote_id = '".$btn_click_row_id."'
";
$statement = $connect->prepare($query);
$statement->execute(
array(
$btn_click_row_id => $_POST["btn_click_row_id"]
)
);
$result = $statement->fetchAll();
// S E C O N D ---------
$query = "
INSERT INTO quote_details (quote_id, quote_details_desc, quote_details_quantity)
SELECT LAST_INSERT_ID(), quote_details_desc, quote_details_quantity
FROM quote_details
WHERE quote_id = '".$btn_click_row_id."'
";
$statement = $connect->prepare($query);
$last_id = $connect->lastInsertId();
$statement->execute(
array(
'$btn_click_row_id' => $_POST["btn_click_row_id"],
'$last_id' => $last_id
)
);
$result = $statement->fetchAll();
$filtered_rows = $statement->rowCount();
if(isset($result))
{
echo $last_id;
}
My theory is I need to do something like the below, but i'm not sure how to get this working properly..
//GET BEFORE MAX ID WHERE QUOTE ID = VERSION SELECT MAX(quote_details_id) AS before_max_id FROM quote_details
//RUN SECOND INSERTION
//GET AFTER MAX ID WHERE QUOTE ID = VERSION SELECT MAX(quote_details_id) AS after_max_id FROM quote_details
//GET RANGE WHERE QUOTE_DETAILS_ID > BEFORE MAX AND <= AFTER MAX SELECT * FROM quote_details WHERE quote_details_id > before_max_id AND quote_details_id <= after_max_id
//FOREACH RANGE VALUE, INSERT INTO QD_ITEMS
/*
INSERT INTO qd_items (qd_item_id, qd_quote_details_id, qd_item_cat_id, qd_item_desc_id, qd_item_notes, qd_item_quantity, qd_item_cost, qd_item_markup, qd_item_total)
SELECT qd_item_id, N E W - V A L U E, qd_item_cat_id, qd_item_desc_id, qd_item_notes, qd_item_quantity, qd_item_cost, qd_item_markup, qd_item_total
FROM quote_details
INNER JOIN quote_details ON quote_details_id = qd_quote_details_id
INNER JOIN quotes ON quotes.quote_id = quote_details.quote_id
*/

Ratio of sum of one column by count of another column

I'm trying to count the number of passed quizzes, as per the following results table:
So, we have 3 quizzes, and if the proportion of correct answers is >= 0.5, then it is passed. If the answer is correct, the result column shows 1, otherwise it shows 0.
For example, quiz 1 has 5 questions, of which 3 are correct. Quiz 2 has 3 questions, of which 1 is correct. Quiz 3 has 2 questions, both are correct.
So, this user has passed 2 quizzes out of 3.
My expected result is: "2 quizzes out of 3 are passed." using MYSQL with PHP with something like:
$number_of_quizzes = 'SELECT COUNT(DISTINCT quiz_id) FROM TABLE'
But, I'm struggling with the query to count the number of rows in the 'result' column and the sum of its values - per quiz.
Is this possible to do with MYSQL alone, or should the logic be transferred to PHP? How?
Can anyone help?
Try this :
$quiz_list = 'SELECT DISTINCT quiz_id FROM TABLE'
$count = 0
$number_of_quizzes = 'SELECT COUNT(DISTINCT quiz_id) FROM TABLE'
foreach ($quiz as &$quiz_list) {
$nb_quiz = 'SELECT COUNT(*) FROM TABLE WHERE quiz_id = ' . $quiz . '';
$nb_correct = 'SELECT COUNT(*) FROM TABLE WHERE quiz_id = ' . $quiz . ' AND result = 1';
$count += ($nb_correct / $nb_quiz > 0.5 ? 1 : 0);
}
$expected_result = $count . " quizzes out of " . $number_of_quizzes . " are passed.";
Of corse you have to change my SQL queries in string to real queries.

Taking mean of all students for one subject using php

I have an SQL table of students with one subject. I would like to take the mean of all the students for this particular subject such that:
Sum of the subject/Number of total students
The table looks like this:
Student ID : 1
=============
Maths : 40
Student ID : 2
=============
Maths : 60
Student ID : 3
=============
Maths : 90
Student ID : 4
=============
Maths : 0
So if the student has scored 0, then ignore this student and its score in calculating the mean.
<?php
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true){
header("location: login.php");
exit;
}
$db = new PDO("mysql:host=localhost; dbname=db;charset=utf8",'user','');
$sql = "SELECT * FROM Students";
$stmt = $db->query($sql);
while($data = $stmt->fetch(PDO::FETCH_OBJ)){
//How to take the mean of 1 subject for all students?
}
?>
Fix this line first so that...you can only get scores greater that 0
$sql = "SELECT * FROM students WHERE subjectscore > 0"; //assuming your column for scores is "subjectscore"
The the rest of the code to get mean should be
$stmt = $db->query($sql);
while($data = $stmt->fetch(PDO::FETCH_OBJ)){
$sumparts .= $data->subjectscore."+"; //Add a delimiter after every returned obj
}
print_r($sumparts); //For debug :to see which ones are selected
$sumarr = explode("+",$sumparts); // Convert the delimited string to array
$sum = array_sum($sumarr); //Get sum of values of array in this case the scores
$divisor = count($sumarr) - 1; //The minus 1 is necessary since well the delimited string will always have 1 extra key therefore making the count to count 1 more unnnecessary key
$total = $sum/$divisor; //Sum of all divided by the total number of objects
echo $total;

delete item the order changes php

I have a page that has a column "order". When I add a new item the order should be 1 + max of the item. But if I delete an item between these values like i have 8 9 10 , if I delete item with 9 the new item will have 11 value and I will have 8 10 11.But I want 8 9 10. How can I do this in php? should I create a function? It works to add a new item with the max+1, but if I delete is not good.
My code:
$queryMaxOrd = mysql_query("select max(ord) from article where user_id=" .$_SESSION['userId']);
$row = mysql_fetch_row($queryMaxOrd);
$valueMaxOrd = $row[0] + 1;
$_SESSION['a'] = $valueMaxOrd;
and the insert query....
Any ideas?
First thing to consider is removing mysql_* and start using mysqli_* or pdo. Your code is vulnerable to sql injections.
With your code structure you have you adding each order as a new record to your table, so when you have 5 orders with one users your table will look like this.
user: Adiiia | order: 5
user: Adiiia | order: 3
user: Adiiia | order: 7
user: Adiiia | order: 2
user: Adiiia | order: 9
when you query the database you are saying to mysql: get me the maximum number of the record i have with user: Adiiia. The result should be 9
If you want to count the sum of the records you should use sum
select sum(ord) from article where user_id='".$_SESSION['userId']."'
The result should be 26
The best thing you can do is by creating a new table orders_sum
The structure should like like this.
Total_orders | User
when a user have a new order you can update the table by adding one or else if have a order removed then removing minus one order.
Something like this.
Total_orders | User
5 | Adiiia
When you want to update:
select Total_orders from orders_sum where User='Adiiia'
Find how many orders the user have by fetching the table.
$orders = $row['Total_orders'];
$plus_orders = $row['Total_orders'] + 1;
update orders_sum set Total_orders='".$plus_orders."' where user='Adiiia'
When you want to delete:
select Total_orders from orders_sum where User='Adiiia'
Find how many orders the user have by fetching the table.
$orders = $row['Total_orders'];
$minus_orders = $row['Total_orders'] - 1;
update orders_sum set Total_orders='".$minus_orders."' where user='Adiiia'
Lets say article table having primary key article_id then after delete any article for user_id. Fetch all the article_id for the user_id. Then update the order for all the article_id for that user.
$queryArticle = mysql_query("select article_id from article where user_id=" .$_SESSION['userId']." order by article_id asc");
$allArticle = [];
while($rowArticle = mysql_fetch_assoc($queryArticle)){
$allArticle[] = $rowArticle['article_id'];
}
$query = "UPDATE article SET ord = (CASE order ";
foreach($allArticle as $order => $article_id) {
$query .= " WHEN {$article_id} THEN {$order}";
}
$query .= " END CASE) WHERE article_id IN (" . implode(",", $allArticle) . ")";

MySQL Count in PHP while loop only returns one result then Null

Ok, so I have some MySQL tables as follows:
Buildings
Building-ID Building-Name
===========----=============
1 Building-1
2 Building-2
3 Building-3
4 Building-4
Building-1
Mroom State
=====----======
1 Booked
2 Empty
3 Empty
4 Empty
Building-2
Mroom State
=====----======
1 Booked
2 Empty
3 Empty
4 Empty
And a query in PHP as follows (Ignore the hard coded while, I've simplified the code a bit):
$sql = "select * from Buildings";
$result = mysql_query ($sql) or die(mysql_error());
while ($row = mysql_fetch_array($result))
{
$building[] = $row['ward_name'];
}
$v1 = 0;
while ($v1 < 4)
{
$sql = "SELECT COUNT(*) FROM `$building[$v1]` WHERE state = 'Empty'";
$result = mysql_query($sql) or die(mysql_error());
$count = mysql_result($result, 00);
var_dump($count[$v1]);
$v1 = $v1 + 1;
}
To my way of thinking this should create an array of the buildings contained in the "Buildings" table, start a loop, load the building name from the array and provide a row count for the table of how many rows contain "Empty" in the state column. What it actually does is provide a count for the first table and then provides "NULL" for the rest.
I'd appreciate any help you can give me.
Cheers!
What about changing your data model?
Table buldings can be kept as is:
Buildings
Building-ID Building-Name
===========----=============
1 Building-1
2 Building-2
3 Building-3
4 Building-4
New table:
Rooms
Building-ID Mroom State
===========-=====-=====
1 1 1
1 2 0
2 1 0
State 0 = Empty, State 1 = Booked
Then use a join with group by:
select count(*) from buildings b inner join rooms r on r.bid = b.id where r.state = 0 group by b.id;
Then you will get a row for each building with the count of empty rooms. You won't need a table for each building.
This does noit make sense:
$count = mysql_result($result, 00);
var_dump($count[$v1]);
you mean to write:
$count[$v1] = mysql_result($result, 00);
var_dump($count[$v1]);
Also do not use several tables with names matching columns of other tables.
You can use one table with a primary key that spans two columns instead, for example create primary key on($buildingid,$roomid)
so that the table has columns $buildingid,$roomid, and $state.
mysql_result() returns a string, not an array.
Modify the code and check that now it works as expected.
var_dump($count);

Categories