Clone / Insert multiple linked tables in PHP PDO and MySQL - php

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
*/

Related

Update multiple rows for 1000 records in one go

I have one table based on which one I have to update 6 rows in the other table for matching ids. It is total of over 1000 records so most of the time I get timeout error with current script.
The way I do it now is, I select the range of ids between two dates from the first table, store it into an array and then run foreach loop making update in the second table where the ids are the same, so basically I run a query for every single id.
Is there anyway I could speed it up the process?
I found only a way to generate the each within the foreach loop
UPDATE product SET price = CASE
WHEN ID = $ID1 THEN $price1
WHEN ID = $ID1 THEN $price2
END
But I don't know how could I modify this to update multiple rows at the same time not just one.
My script code look like that
$sql = "SELECT * FROM `games` where (ev_tstamp >= '".$timestamp1."' and ev_tstamp <= '".$timestamp2."')";
while($row = mysqli_fetch_array($sql1)){
$one_of =[
"fix_id" =>$row['fix_id'],
"t1_res" =>$row['t1_res'],
"t2_res" =>$row['t2_res'],
"ht_res_t1" =>$row['ht_res_t1'],
"ht_res_t2" =>$row['ht_res_t2'],
"y_card_t1" =>$row['y_card_t1'],
"y_card_t2" =>$row['y_card_t2'],
"t1_corners" =>$row['t1_corners'],
"t2_corners" =>$row['t2_corners'],
"red_card_t1" =>$row['red_card_t1'],
"red_card_t2" =>$row['red_card_t2']
];
array_push($today_games,$one_of);
}
foreach($today_games as $key=>$val){
$cards_t1=$val['red_card_t1']+$val['y_card_t1'];
$cards_t2=$val['red_card_t2']+$val['y_card_t2'];
$sql = "Update sights SET t1_res='".$val['t1_res']."',
t2_res='".$val['t2_res']."', ev_tstamp='".$val['ev_tstamp']."',
ht_res_t1='".$val['ht_res_t1']."', ht_res_t2='".$val['ht_res_t2']."',
t1_corners='".$val['t1_corners']."',t2_corners='".$val['t2_corners']."',
t1_cards='".$cards_t1."',t2_cards='".$cards_t2."'
where fix_id='".$val['fix_id']."' "
}
Consider an UPDATE...JOIN query using fix_id as join column. Below runs mysqli parameterized query using timestamps. No loop needed.
$sql = "UPDATE sights s
INNER JOIN `games` g
ON s.fix_id = g.fix_id
AND g.ev_tstamp >= ? and g.ev_tstamp <= ?
SET s.t1_res. = g.t1_res,
s.t2_res. = g.t2_res,
s.ev_tstamp = g.ev_tstamp,
s.ht_res_t1 = g.ht_res_t1,
s.ht_res_t2 = g.ht_res_t2,
s.t1_corners = g.t1_corners,
s.t2_corners = g.t2_corners,
s.t1_cards = (g.red_card_t1 + g.y_card_t1),
s.t2_cards = (g.red_card_t2 + g.y_card_t2)";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, 'ss', $timestamp1, $timestamp2);
mysqli_stmt_execute($stmt);

PHP / SQL: Update Table C if meet condition after updated in Table A and Table B

I got some issues with my current code. Example, on a PHP page, there's a table that displays all tools that borrowed the users. In that table, each data rows contain a checkbox. Users can select any tools that they want to return first by tick the checkbox and press "return" button.
At Server-side, after clicking the "return" button, it will go to the page named return_selected.php. At this page, it will update Table A and Table B. This one is successful.
Now, I want to update Table C if all there's a condition, for example, ALL tools returned. This one I still do but failed. Below is the code
return_selected.php
<?php
include("../../../../config/configPDO.php");
include("../../../../config/check.php");
$tools_id = $_POST['tools_id'];
$borrow_id = $_POST['borrow_id'];
$checkbox=explode( ',', $_POST['ids'][0] );
for($i=0;$i < count($checkbox); $i++){
$tools_id=$checkbox[$i];
$sql="UPDATE ets_tools SET borrow_id = NULL WHERE tools_id=:tools_id";
$query=$conn->prepare($sql);
$query->execute(array(':tools_id' => $tools_id));
$sql2="UPDATE ets_tools_borrow SET time_to = GETDATE() WHERE tools_id=:tools_id";
$query3=$conn->prepare($sql2);
$query3->execute(array(':tools_id' => $tools_id));
// want to update table if all tools returned.
$query2 = "
SELECT
ets_tools.tools_id, ets_tools.tools_name, ets_tools.borrow_id,
ets_borrow.time_from, ets_borrow.time_to, ets_borrow.status_id
FROM ets_tools
INNER JOIN ets_borrow ON ets_tools.borrow_id = ets_borrow.borrow_id
WHERE ets_tools.borrow_id IS NOT NULL AND ets_borrow.borrow_id = :borrow_id
";
$sql2=$conn->prepare($query2);
$sql2->execute(array(':borrow_id' => $borrow_id));
if($sql2->rowCount() > 0)
{
header("Location: return.php");
}else{
$sql3="UPDATE ets_borrow SET time_to = GETDATE(), status_id = 2 WHERE borrow_id=:borrow_id";
$query3=$conn->prepare($sql3);
$query3->execute(array(':borrow_id' => $borrow_id));
header("Location: return.php");
}
}
?>
Can anyone know how to solve this? Thank you.
You need to consider the following:
As is mentioned in the documentation, PDOStatement::rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object and for most databases the number of rows returned from a SELECT statement is not returned correctly. So, you may use a SELECT COUNT(*) ... approach to get this count.
For your specific case you may try to use an UPDATE ... WHERE NOT EXISTS ... statement to update the rows in the ets_borrow table and skip this SELECT ... FROM ... INNER JOIN ... statement.
I'm not sure if I understand corectly the use of header("Location: return.php"); in a for loop, probably you need to redirect after this loop.
Example, based on your code:
<?php
include("../../../../config/configPDO.php");
include("../../../../config/check.php");
$tools_id = $_POST['tools_id'];
$borrow_id = $_POST['borrow_id'];
$checkbox=explode( ',', $_POST['ids'][0] );
for($i=0; $i < count($checkbox); $i++) {
$tools_id=$checkbox[$i];
$sql = "UPDATE ets_tools SET borrow_id = NULL WHERE tools_id = :tools_id";
$query = $conn->prepare($sql);
$query->execute(array(':tools_id' => $tools_id));
$sql2 = "UPDATE ets_tools_borrow SET time_to = GETDATE() WHERE tools_id = :tools_id";
$query2 = $conn->prepare($sql2);
$query2->execute(array(':tools_id' => $tools_id));
$sql3 = "
UPDATE ets_borrow
SET time_to = GETDATE(), status_id = 2
WHERE
(borrow_id = :borrow_id1) AND
NOT EXISTS (
SELECT 1
FROM ets_tools
INNER JOIN ets_borrow ON ets_tools.borrow_id = ets_borrow.borrow_id
WHERE ets_tools.borrow_id IS NOT NULL AND ets_borrow.borrow_id = :borrow_id2
)
";
$borrow_id1 = $borrow_id;
$borrow_id2 = $borrow_id;
$query3 = $conn->prepare($sql3);
$query3->execute(array(':borrow_id1' => $borrow_id1, ':borrow_id2' => $borrow_id2));
}
header("Location: return.php");
?>

Update Inner Join two tables

** Table Inputs**
(id_inpits, name, quantity_inputs)
Table Outputs
`(id_outputs, name_outputs, quantity_outputs, quantity_disponible)
when I want to update the quantity_output, and calculate the quantity_disponbile
knowing that : quantity_disponbile = quantity_inputs - quantity_output
I tried with :
if(!empty($_POST['do'])) {
$m_id = $_POST['id_output'];
$quantity_outputs = $_POST["quantity_outputs"];
$sql = $db->query("UPDATE outputs AS o INNER JOIN inputs As i ON i.id_input = o.inputs_id SET o.quantity_dispo = 'select quantity_inputs from inputs - FROM (select quantity_outputs from outputs )', o.quantity_outputs = '$quantity_outputs' WHERE o.id_output =' $m_id'");
if(!$sql) {
die(mysql_error());
}
}
One suggestion: quantity_disponbile is supposed a calculated field from both table. So split the logic into two: one select query and one update query. The update query just need to update the quantity_output, and the select query can be like:
select
i.quantity_inputs - o.quantity_output = quantity_disponible
from output o
inner join input i on i.id_inpits = o.inputs_id
I don't correct the typo anyway

How could I execute this basic table query in PHP?

Suppose I have a table TABLE:
NAME ID ...
m -1 ...
f -1 ...
g -1 ...
b -1 ...
z -1 ...
And I want to turn it into:
NAME ID ...
f 1 ...
g 2 ...
m 3 ...
b -1 ...
z -1 ...
You probably get the idea:
select the first 3 rows from the original table (preserving order)
order selected rows by the NAME column.
update selected rows' IDs with their position in the new table (keeping the remaining unselected rows in their original positions).
So (m, f, g) got sorted to (f, g, m) and (b, z) remained (b, z).
Here's how I am trying to do it in PHP:
$count = 0;
$query = "UPDATE TABLE SET ID = $count:= $count + 1 ORDER by NAME DESC LIMIT 3";
mysqli_query($con, $query);
But I don't think I can just go ahead and increment a counter and store its value like that. Any advice?
You can try this :
$limit = 3;
for($count = 0 ; $count < $limit;$count++ ){
$query = "UPDATE TABLE SET ID = $count + 1 WHERE ID = '-1' ORDER by NAME DESC";
mysqli_query($con, $query);
}
$query = "UPDATE TABLE SET ID = '-1' WHERE ID > $limit ORDER by NAME DESC";
mysqli_query($con, $query);
In the above logic :
In the final loop, all the IDs are set to $limit
However the update command outisde the loop will set back IDs to -1 again
First, you can quickly query for the first 3 rows in the table and get the name property only and assign the value in an array.
$sql = "select name from table order by name limit 3"
$query = $mysqli->query($sql);
Now let's construct a helper array:
while ($row = $mysqli->fetch_assoc()) {
$a[] = $row['name'];
}
Now just structure the queries:
foreach($a as $id => $name) {
$query = "update table set id={$id+1} where name='$name' limit 1";
// execute the query
}
Note that I assume that the name is unique so I added the limit 1 directive to tell it stop looking for rows to update once it has found a row.
Also, don't forget that array keys are counting starting from 0, hence we are adding 1 to the $id in the loop.
There may be more elegant solutions but this one is rather easy to understand and use.
In MySQL:
SET #row_number = 0;
update TABLE d
join
(
select
NAME,
#row_number:=#row_number+1 as ID,
from
(select NAME from TABLE limit 3) t
order by
NAME asc
) s on s.NAME = d.NAME
set d.ID = s.ID;
SQLFiddle: http://sqlfiddle.com/#!9/dffecf/1
This assumes NAME is your unique key, otherwise likely best to replace with an Identity column in your table and use that for the update.
This approach may require some syntax changes depending on your DB engine. By doing this in SQL, we only make one pass at the DB. Not a huge deal to iterate in multiple passes with PHP if you're only updating three records, but if it was a 1000, etc.

Query multiple totals at once in MYSQL PHP

I have a a table in my DB that has multiple columns with numbers I would like to query all the rows in 1 query with separate totals for all rows in each column in my db.
like so
$sql = '
SELECT sum(TOTAL1)
, sum(TOTAL2)
, sum(TOTAL3)
, sum(TOTAL4)
FROM TABLE WHERE ID = '.$ID.'';
it works when I do it with a single column query like this.
$sql = 'SELECT sum(TOTAL1) FROM TABLE WHERE ID = '.$ID.'';
but I can't seem to get it to work for multiples in 1 query does anyone know of a more proper way of doing this instead of in separate queries?
$sql = 'SELECT (sum(TOTAL1)+sum(TOTAL2)+sum(TOTAL3)+sum(TOTAL4)) AS FINALTOTAL FROM TABLE WHERE ID = '.$ID.'';
Use aliases.
Sidenote: Add your WHERE clause to the tested examples I've given below.
SELECT sum(TOTAL1) as total1, sum(TOTAL2) as total2
which if you want to use seperate aliases, is handy if you wish to echo them as different entities.
For example:
$query = mysqli_query($con, "SELECT SUM(col1) as total1,
SUM(col2) as total2,
SUM(col3) as total3 FROM table ");
while($row = mysqli_fetch_array($query)){
echo $row['total1']; // echo'd 125
echo "<br>";
echo $row['total2']; // echo'd 225
echo "<br>";
echo $row['total3']; // echo'd 2000
}
Sidenote: My three columns contained the following:
col1 in 2 rows 25, 100
col2 in 2 rows 25, 200
col3 in 2 rows 1000, 1000
To echo the total of all rows and for example: (and inside the while loop)
$total = $row['total1'] + $row['total2'] + $row['total3'];
echo $total;
Or in one go and as one alias and one row echo'd:
SELECT sum(TOTAL1 + TOTAL2 + TOTAL3) as total FROM table
I.e.:
$query = mysqli_query($con, "SELECT SUM(col1 + col2 + col3) as total FROM table ");
while($row = mysqli_fetch_array($query)){
echo $row['total'];
}
NOTE: DATA TYPE must be same for all fields which you want to SUM
By following query you can have SUM(field1)+SUM(field2)+ SUM(field3) .....n in 1 single field
I used this query for just 2 fields and both are integers
See this is my table definition
create table `siso_area_operativa` (
`id_area_operativa` int ,
`area_operativa` varchar (8),
`responsable` int
);
and this is query which you want
SELECT SUM(a.field1) FROM
(
SELECT
SUM(id_area_operativa) field1
FROM
siso_area_operativa
UNION ALL
SELECT SUM(responsable) field1
FROM
siso_area_operativa ) AS a
Result of this is
SUM(id_area_operativa) + SUM(responsable) in single field
ENJOY !!!!!!!!!!!!

Categories