Insert fails while loop in pdo (pdo/php 5.6) - php

I've wrote a script in PHP for an university big data project.
The following code should support following function:
Read amount of data from a table
read a subset of the same table und extend it with 2 columns which calculate 2 values.
generate f.e. 1000 inserts and commit them to an other table
do this for the whole dataset of point 1
My problem:
0-1000:
my solution inserts in the first try 1000 datalines
1000-2000:
in this step it inserts 2000 datalines, so after the 2nd step it seems to insert 0-2000 datalines of the origin dataset. In sum 3000 datalines.
I'm a little bit out of ideas... I don't see my failure.
<?php
$user = 'root';
$pass = '';
$kill = 0;
echo 'Connecting to DB:';
try {
$db1 = new PDO('mysql:host=localhost;dbname=itt2_joined;charset=utf8',$user,$pass);
$db1->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
echo "OK \nGOING2COPY!\n";
}
catch(PDOException $ex) {
echo " Failed - Process stopped!\n";
$kill = 1;
}
if(!$kill) {
$stmt = 'SELECT
`id_transaction`
FROM
`database_joined_full`
WHERE
`relative_delivery_date` > 0
AND
`relative_received_date` > 0
AND
`relative_issued_date` > 0';
$setSize = $db1->query($stmt)->rowCount();
echo "No. Of Datasets: " . $setSize . "\n";
$stepSize = 1000;
echo "Start Copy $stepSize Datasets per Query! \n";
$copy = 1;
$lower = 0;
$upper = 0;
echo "[";
while($copy) {
$lower = $upper;
$upper += $stepSize;
$upper = ($upper > $setSize ? $setSize : $upper);
$data = $db1->query("SELECT
`id_transaction`,
`id_order_line`,
`relative_transaction_date`,
`relative_requested_date`,
`new_requested_qty`, `new_requested_price`,
`relative_suggested_date`,
`new_suggested_qty`,
`delivery_qty`,
`relative_delivery_date`,
`received_qty`,
`relative_received_date`,
`id_order_header`,
`delivery_counter`,
`relative_issued_date`,
`relative_xcurrent_date`,
`issued_quantity`,
`current_quantity`,
`product_code`,
`destination`,
`relative_issuing_date`,
`delivery_location`,
`issuer`,
`id_supplier`,
`currency`,
`shipment`,
`issued_price4unit`,
`current_price4unit`,
`total_delivered`
FROM
`database_joined_full`
WHERE
`relative_delivery_date` > 0
AND
`relative_received_date` > 0
AND
`relative_issued_date` > 0
LIMIT $lower OFFSET $stepSize")->fetchAll();
$db1->beginTransaction();
foreach($data as $row) {
$sql = "";
$sql = "INSERT INTO `refactored_data` (`id_transaction`, `id_order_line`, `relative_transaction_date`,
`relative_requested_date`, `new_requested_qty`, `new_requested_price`, `relative_suggested_date`,
`new_suggested_qty`, `delivery_qty`, `relative_delivery_date`, `received_qty`,
`relative_received_date`, `id_order_header`, `delivery_counter`, `relative_issued_date`,
`relative_xcurrent_date`, `issued_quantity`, `current_quantity`, `product_code`, `destination`,
`relative_issuing_date`, `delivery_location`, `issuer`, `id_supplier`, `currency`, `shipment`,
`issued_price4unit`, `current_price4unit`, `total_delivered`, `shipment_delay`, `sending_delayed`) VALUES ";
$sql .= "(";
for($i = 0; $i<sizeof($row)/2; $i++) {
$sql .= "'".$row[$i] . "', ";
}
$sql .= $row['relative_received_date'] - $row['relative_delivery_date'] . ',';
$sql .= ($row['relative_received_date'] <= $row['relative_issued_date'] ? 1 : 0) .')';
$db1->prepare($sql)->execute();
}
$db1->commit();
// Statusbar
//echo "\n$lower - $upper\n";
$perc = ceil(($upper/$setSize) *40);
$bar = "\r[". str_repeat("=", $perc - 1). ">";
$bar .= str_repeat(" ", 40 - $perc) . "] - " . number_format($upper / $setSize * 100, 3) ."% ";
echo "\033$bar"; // Note the \033. Put the cursor at the beginning of the line
//While_Exit
$copy = ($upper == $setSize ? 0 : 1);
//$copy = 0;
}
echo "\nall done, BYE! \n";
}
?>

You're using the stepsize as the offset each time:
LIMIT $lower OFFSET $stepSize
Should be:
LIMIT $stepSize OFFSET $lower

Oh thank you! I haven't seen the failure.
Now the code works, nearly completely, my last problem is the following:
in the first Select query i get from '->rowCount();' the number of rows of the select query.
But with my insertion copys a bit more data. But in the second Select i have the same Where clause likewise the first Select query.
I get from the CLI-Print : No. of Rows: 655056
and it writes in the Database 658597
so how do i get the 3541 rows?
or is maybe a failure inside the Insert?
Greetings

Related

PHP - Finding consecutive values in multidimensional associative arrays for seat reservation program

I'm working on a program to reserve seats for a show. I have a multidimensional array that is created using $row and $column variables. After making a few initial reservations, I need to pass integers into a function/some code to make further reservations.
I've tried looping through the array to find consecutive available seats (value "avail") but it ignores reserved seats or skips over them. I'll need to later use manhattan distance to reserve the best seats (from row 1, seat 6) first.
function to create the array:
//function to create seating chart data structure
function createChart($row, $column){
//create array for row values
$row_chart = array();
for($r=0; $r < $row; $r++){
$row_number = $r + 1;
$row_chart[$row_number] = array(); // array of cells for row $r
}
//create array for column values
$column_chart = array();
for($c=0; $c < $column; $c++){
$column_number = $c + 1;
//$location = $c_num;
$status = "avail";
foreach($row_chart as $key => $value){
$column_chart[$column_number] = $status; //add arrays of "seats" for each row
}
}
//nest the column array into the row array
foreach($row_chart as $key => $value){
foreach($column_chart as $k => $v){
$seating_chart[$key][$k] = $status;
}
}
//$seating_chart = array_combine($row_chart, $column_chart);
return $seating_chart;
}
function to make initial reservations:
$initial_reservation = "R1C4 R1C6 R2C3 R2C7 R3C9 R3C10";
$initial_reservation = explode(" ", $initial_reservation);
echo "<br> <br>";
print_r($initial_reservation);
$initial_res_length = count($initial_reservation);
echo "<br> <br>";
//echo $initial_res_length;
//split each seat up into integers to mark it reserved in the array
//issue for flexibility: find way to break up string by letters and numbers for larger charts
for($a = 0; $a < $initial_res_length; $a++){
$reso_row = substr($initial_reservation[$a], 1, 1);
//echo $reso_row . "<br>";
$reso_column = substr($initial_reservation[$a], 3, 2);
//echo $reso_column . "<br>";
$working_chart[$reso_row][$reso_column] = "reserved";
}
//echo "<br> <br>";
//echo "<pre>" . print_r($working_chart, 1) . "</pre>";
what I have so far in attempt to make further reservations:
//write some code to find consecutive seats
$seats_needed = 4;
$outer_array_length = count($working_chart);
//echo $outer_array_length;
for($d = 1; $d < $outer_array_length + 1; $d++){
for($e = 1; $e < $seats_needed + 1; $e++){
//issue: run through $seats_needed amount of times and executes the code block
//needed: check if $seats_needed amount of seats in available first then run reservation code
if($working_chart[$d][$e] === "avail"){
$working_chart[$d][$e] = "new reservation";
}
else{
echo "Sorry, not possible.";
}
}
break;
}
echo "<br> <br>";
echo "<pre>" . print_r($working_chart, 1) . "</pre>";
I'd like to be able to find a number of available seats ($seats_needed) first, and then loop through to reserve them.
I have initialized the $working_chart with :
$working_chart = createChart(10, 11);
I have written the attempt to make further reservations :
foreach(array_keys($working_chart) as $d ){
$maxColumn = count($working_chart[$d]) - $seats_needed + 1;
for($e = 1; $e <= $maxColumn ; $e++){
if(["avail"] === array_unique(array_slice($working_chart[$d], $e - 1 , $seats_needed))){
$working_chart[$d] = array_replace($working_chart[$d], array_fill($e, $seats_needed, "new reservation"));
break 2;
}
else{
echo "Sorry, not possible.";
}
}
}
I hope it can help you...

Gain Xp and level PHP & MYSQL

I have this script for my site and I think I have a problem in the for line. If I update my user_xp_amount with 256 the script works fine. However, when I update with a higher XP, such as 785, the script is showing me that I have level 1 instead of level 2 with 256xp. Why is this not behaving the way I desire?
PHP Script:
<?php
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$user_id = 4;
function get_user_xp($user_id, $mysqli) {
$sql = $mysqli->query("SELECT user_xp_amount FROM users_xp WHERE user_id='$user_id'");
$row = $sql->fetch_assoc();
return $row['user_xp_amount'];
}
$xp = array(0,256,785,1656,2654);
$my_xp = get_user_xp($user_id, $mysqli); // where 4 is my user id
for($i = 0; $i < count($xp); $i++) {
if($my_xp == $xp[$i]) {
echo 'I\'m on level ', ($i+1);
break;
}
else {
if(isset($xp[$i+1])) {
if($my_xp > $xp[$i] && $my_xp <= $xp[$i + 1]) {
echo 'My next level is ', ($i+2), ' and I need ', $xp[$i+1], ' more points for achieving it!';
break;
} else {
echo 'My next level is ', ($i+1), ' and I need ', $xp[$i], ' more points for achieving it!';
break;
}
}
}
}
?>
MySQL DB:
user_xp_id Primar bigint(20) | user_id bigint(20) | user_xp_amount bigint(20)
The reason it's not working can be found with some basic debugging: think through your for loop step by step. If that fails, try something like
// snip
for($i = 0; $i < count($xp); $i++) {
print $i; // show me which step I'm on
if($my_xp == $xp[$i]) {
// snip
Try that, and the reason will pop out at you.
This is an essential part of debugging: be careful what you assume. Your assumption is usually your mistake.
Only after you go through that exercise should you look any further into this answer. (You may not even want to!)
A hint that'll make it easier to code: you can keep reassigning values until you exit the loop.
$xp = array(0,256,785,1656,2654);
$my_xp = 254;
for($i = 0; $i < count($xp); $i++) {
// if we've looped beyond our xp, exit with last assigned (current) values
if($my_xp < $xp[$i]) { break; }
$my_level = $i;
// if index + 1 is in range, assign values
if($i+1<count($xp)) {
$next_level = $i+1;
$xp_needed = $xp[$i+1] - $my_xp;
// if index + 1 is out of range, give default values
} else {
$next_level = $i;
$xp_needed = 0;
}
}
printf("<div>Current Level: %d (%d xp)</div>" .
"<div>Next Level: %d (%d xp)</div>" .
"<div>XP Needed: %d</div>",
$my_level +1, // correct off-by-1 error of index
$my_xp,
$next_level +1, // correct off-by-1 error of index
$xp[$next_level],
$xp_needed
);

How do I divide an integer over multiple values in PHP?

I'm trying to make a little PHP script for fun, and I'm a little stuck.
I want to divide an integer (for example 5) over multiple values.
For example:
$total = 5;
$mike = 0;
$ralf = 0;
$ashley = 0;
// Run the magic here
echo "Mike has " . $mike . " apples, Ralf has " . $ralf ." apples and Ashley has " . $ashley . " apples";
The output that I expect would look something like this:
Mike has 2 apples, Ralf has 1 apples and Ashley has 2 apples
Is there a way how to do this? :)
I can't do this hard coded, because I want the values to be randomized.
Cheers
Do it like this:
$total = 5;
$mike = rand(1,$total-2); // so that max value is 3 (everyone should get at least 1) ($total - $numberOfVarsToDistributeTheValueTo + 1)
$ralf = rand(1,$total - $mike - 1); // if 3 goes to mike, only 1 goes to ralf
$ashley = $total - $mike - $ralf; // i hope you understand.
// use it.
Something like this would work:
$people = array('mike','ralf','ashley');
$num = count($people);
$sum = 5; // TOTAL SUM TO DIVIDE
$groups = array();
$group = 0;
while(array_sum($groups) != $sum) {
$groups[$group] = mt_rand(0, $sum/mt_rand(1,5));
if(++$group == $num){
$group = 0;
}
}
// COMBINE ARRAY KEYS WITH VALUES
$total = array_combine($people, $groups);
echo "Mike has " . $total['mike'] . " apples, Ralf has " . $total['ralf'] ." apples and Ashley has " . $total['ashley'] . " apples";
Solution is inspired from this answer: https://stackoverflow.com/a/7289357/1363190
Hope This function will do your work . it can work for variable # of persons also.
divide_items(10,['mike','ralf','ashley']);
function divide_items($total=1,array $persons){
$progressed = 0;
for($i=0;$i<count($persons);$i++){
echo $random_count = rand(1,$total);
if(($i==(count($persons)-1)) && $progressed<$total ){
$random_count1 =$total - $progressed;
echo $persons[$i]." has ".$random_count1 ." Items<br>";
continue;
}
$progressed = $progressed+$random_count;
if($progressed<=$total){
echo $persons[$i]." has ".$random_count ." Items<br>";
}else{
echo $persons[$i]." has 0 Item<br>";
}
$total = $total-$random_count;
$progressed = 0;
}
}

Query in a while loop, how can I improve the speed of this? Two DB Types

edit
Thought i need to add more info. This first query is MySQL, the latter two are PGSQL, and its located on a seperate server. When i disable the second query in the second part of this, its still just as slow.
SELECT n.id, n.number, n.assigned, n.btn, n.status as stat, s.status
FROM numbers n
LEFT JOIN status s on n.status=s.id
where number like '239333%'
LIMIT $start, $limit
I have the following query, this pulls a range of numbers from a DB, this is a pretty quick query, as I have it limited to 50 or 100.
This lists the output in a while loop in PHP..
Within this while loop, there is a second connection to a seperate server (postgres) to do additional checks on this number which is done through a function, so in the loop i have for example $mq = addition_checks($number);
$query = "SELECT count(baseinformation_directorynumber) as count FROM \"public\".\"meta_subscriber\" WHERE baseinformation_directorynumber = $number";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
$row = pg_fetch_assoc($result);
$did = "0";
if ($row['count'] == '0') {
$query2 = "SELECT count(lastdirectorynumber) as count FROM \"public\".\"meta_pbx_directinwardcalling\" where firstdirectorynumber <= $number and $number <= lastdirectorynumber";
$result2 = pg_query($query2) or die('Query failed: ' . pg_last_error());
$row2 = pg_fetch_assoc($result2);
if ($row2['count'] == '1') {
$did = $row2['count'];
$row['count'] = "0";
}
}
pg_free_result($result);
// Closing connection
$line = $row['count'];
$match = array('line' => $line, 'did' => $did);
return $match;
After this I do a couple more checks to display the information as needed.
The problem is that when I added the additional_checks query, it takes about 30 seconds to load 50 items. Im asking (due to lack of knowledge) how I can increase the speed of this to be a little more acceptable.
If it helps, here it my main while look
while ($q->getrow()) {
$number = $q->field('number'); $assigned = $q->field('assigned'); $btn = $q->field('btn'); $id = $q->field('id'); $status = $q->field('status'); $stat = $q->field('stat');
$nc++; //Start Counter
$now = time();
$diff = $now - $time;
if ($alternate == "1") {
$color = "#EFEFEF";
$alternate = "2";
} else {
$color = "#DFDFDF";
$alternate = "1";
}
$match = meta_query($q->field('number'));
if ($match['line'] == '1' and $match['did'] == '0') {
$numcolor = "green";
$did = "";
} elseif ($match['did'] == '1' AND $match['line'] == '0') {
$did = "[DID]";
$numcolor = "green";
} else {
$did = "";
if ((!$assigned) AND (!$btn) AND ($stat == '1' OR $stat == '4')) {
$numcolor = "";
} else {
$numcolor = "red";
}
}
//if ($numcolor = "red" AND $assigned == '' AND $btn == '' AND $stat == '1') {
// $numcolor = "";
//}
//print_r($match);
if ($stat == '4') { $color = "C2FACB"; }
elseif ($stat == '2') { $color="FCFBEA"; }
// else {
$ajaxedits .= "EditInPlace.makeEditable({ id: 'btn:$id' });\n";
$ajaxedits .= "EditInPlace.makeEditable({ id: 'assigned:$id' });\n";
$ajaxedits .= "EditInPlace.makeEditable({
id: 'status:$id',
type: 'select',
save_url: 'optionedit_eip.php',
options: {
1: 'Free',
2: 'In use',
3: 'Disconnected',
4: 'Ported Out'
}
});";
//}
//<span class="red" id="status:$id">Dark Green</span>
//
if (isset($right[admin])) {
$clear = " (Clear)";
}
eval("\$list_numbers .= \"".addslashes($TI[5])."\";");
}
$q->free;
the following
$match = meta_query($q->field('number'));
is the function where it calls to do the additional postgres checks which is listed above. Yes my code is ugly, im still a noob. :)
SQL queries within loops can be avoided. One way is to collect all $numbers in a php array and then run a single query after the loop.
..WHERE baseinformation_directorynumber IN ($num1, $num2, ...);
You'll get counts of all numbers in a single go. This will speed up the execution.
I've found a blog post containing more ways to avoid sql in loops. check article
Look into using a JOIN on the two tables. Then you can compare the speeds, but depending on the number of rows that you have, a JOIN should be quicker than two queries.

Fatal error: Unsupported operand types

I Keep getting the following error and I was wondering on how to fix it.
Fatal error: Unsupported operand types on line 97
Its around this area of code listed below. I can list the full code if needed.
PHP code
$total_rating_points = mysqli_fetch_array($result);
if (!empty($total_rating_points) && !empty($total_ratings)){
$avg = (round($total_rating_points / $total_ratings,1));
$votes = $total_ratings;
echo $avg . "/10 (" . $votes . " votes cast)";
} else {
echo '(no votes cast)';
}
Here is Line 97
$avg = (round($total_rating_points / $total_ratings,1));
Here is the full code.
function getRatingText(){
$dbc = mysqli_connect ("localhost", "root", "", "sitename");
$page = '3';
$sql1 = "SELECT COUNT(*)
FROM articles_grades
WHERE users_articles_id = '$page'";
$result = mysqli_query($dbc,$sql1);
if (!mysqli_query($dbc, $sql1)) {
print mysqli_error($dbc);
return;
}
$total_ratings = mysqli_fetch_array($result);
$sql2 = "SELECT COUNT(*)
FROM grades
JOIN articles_grades ON grades.id = articles_grades.grade_id
WHERE articles_grades.users_articles_id = '$page'";
$result = mysqli_query($dbc,$sql2);
if (!mysqli_query($dbc, $sql2)) {
print mysqli_error($dbc);
return;
}
$total_rating_points = mysqli_fetch_array($result);
if (!empty($total_rating_points) && !empty($total_ratings)){
$avg = (round($total_rating_points / $total_ratings,1));
$votes = $total_ratings;
echo $avg . "/10 (" . $votes . " votes cast)";
} else {
echo '(no votes cast)';
}
}
$total_rating_points is an array. you cannot divide it by a number.
(edited since the MySQL query was added to the question)
You've used mysql_fetch_array to get your result from MySQL, as the name suggests this returns an array. You can't do math like that on arrays.
You want to change your MySQL query to this:
$sql1 = "SELECT COUNT(*) as count
FROM articles_grades
WHERE users_articles_id = '$page'";
Change your mysql_fetch_array code to this:
$total_rating_points = mysql_result($result, 0, "count");
That will return the actual number, which you can then use for math. Change both of your queries to this format and you should be good to go.
That's usually caused when the type of one of your variables is something you're not expecting it to be.
$x = "8";
$y = 4;
$x / $y; // this is OK, PHP converts "8" to 8
$x = new FooObject();
$y = 4;
$x / $y; // PHP says "wtfmate??"
Dump out the variables $total_rating_points and $total_ratings:
var_dump($total_rating_points);
var_dump($total_ratings);
.. then work backwards through your code (checking debug_backtrace() if required) to find where it went awry.
Edit: duhhh.. I just looked at your code again and saw the issue. The $total_rating_points is an array, and this is the cause of the problem. How do you divide an array by a number? Answer: you can't.
Do you want to divide each of the members of the array by $total_ratings? eg:
// input: [2, 4, 6, 16] / 2
// output: [1, 2, 3, 8]
function divideArrayMembers($arr, $denominator) {
$ret = array();
foreach ($arr as $key => $val) {
$ret[$key] = $val / $denominator;
}
return $ret;
}
...or do you want to divide the total?
input: [2, 4, 6, 16] / 2
output: 14 // (2 + 4 + 6 + 16) / 2
function divideTotal($arr, $denominator) {
return array_sum($arr) / $denominator.
}
Use array_sum() on $total_rating_points and $total_ratings.
if($_REQUEST['cityCode'] != ''){
$_SESSION['Cri_locations'] = $_REQUEST["s"];
$_SESSION['Cri_DateFrom'] = $_REQUEST["startDate"];
$_SESSION['Cri_DateTo'] = $_REQUEST["endDate"];
$what_to_search_id =str_replace("AREA-","",$_REQUEST["cityCode"]);
$total_adults =0;
$total_childs =0;
$child_ages =0;
$no_of_room =0;
for($i=1;$i<=$_REQUEST["Cri_noofRooms"];$i++){
$check_adults =$_REQUEST['adults-r'.$i.''];
if($check_adults>0){
$adults =$_REQUEST['adults-r'.$i.''];
$childs =$_REQUEST['childs-r'.$i.''];
$childAge =$_REQUEST['childAge-r'.$i.''];
$packs_arr[] =array('adults'=>$adults,'childs'=>$childs,'childAge'=>$childAge);
$total_adults =$total_adults+$adults;
$total_childs =$total_childs+$childs;
$child_ages =$child_ages+$childAge;//error accours here pls help
$no_of_room =$no_of_room+1;
}
}

Categories