Retrieve array from postgres - php

Very basic question but couldn´t find a solution.
In a table with some values I try to store in 1 column a array (int[]) and retrieve it. The storing and searching works fine but if I select it I get it as string in php.
Table week
col id (int) = 1
col days (int[]) = {1,1,1,1,1,0,0}
PHP
$query = SELECT id, days, manyother FROM week //array_to_json(days) does the same result
$pdo->setAttribute( PDO::ATTR_CASE, PDO::CASE_NATURAL );
$result = $pdo->query($query);
$test = $result->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($test)
Returns:
id: 1
days: "[1,1,1,1,1,0,0]"
manyother: ""
I´m sure I miss just something with json_encode/decode
Edit: its not affected by json_encode, I debuged it and before it returns the value like '[1,1,1,1,1,0,0]'.
Edit 2: Found a solution which works but increases the loading time 15* times :D So the question is still open but I have a workaround for the moment.
foreach($test as $key => $value){
$test[$key]['days'] = json_decode($value['days']);
}

when selecting array, you can hack the way array is displayed:
t=# select json_build_array(array[1,2,3,4])->0;
?column?
-----------
[1,2,3,4]
(1 row)
It should be easily evaluated by php then with eval. Or even json_agg on whole data set and then eval:
t=# select json_agg(s162) from s162;
json_agg
[{"i":0,"a":[1,2,3,4]},
{"i":1,"a":[1,4]}]
(1 row)
Time: 0.281 ms

Related

insert query data into same sql query

I am trying to insert the data of a query, currently I am doing it with the eloquent ORM of laravel, but it takes a long time since there are approximately 120k of records, so I would like to know if they can help me as it can be done in the same query
This is the query:
$var = DB::select("
select selrs.*, sim.emin, sim.emax
from (select rac.*, sup.zona, sup.sitio, sup.manejo
from datos_rendim_actual rac
left join super sup on (sup.codigo = (rac.fundo::int8 * 1000000 + rac.rodal::int8 ))) selrs
left join sitman sim on (sim.sitio = selrs.sitio and sim.manejo = selrs.manejo)
where selrs.edad >= sim.emin and selrs.edad <= sim.emax
");
This is the dd of $var
array:123921 [▼
0 => {#813 ▼
+"id": 255214
+"fundo": 101
+"rodal": 196826
+"codigo": null
+"edad": 10
+"densidad": "1019"
+"vol_prod1": "0"
+"vol_prod2": "113.95"
+"created_at": null
+"updated_at": null
+"zona": 5
+"sitio": 1
+"manejo": 7
+"emin": 10
+"emax": 20
}
So This is how I insert them:
foreach ($var as $lista) {
$rendimA = new RendimActual;
$rendimA->codigo = $lista->fundo.$lista->rodal;
$rendimA->edad = $lista->edad;
$rendimA->densidad = $lista->densidad;
$rendimA->vol_prod1 = $lista->vol_prod1;
$rendimA->vol_prod2 = $lista->vol_prod2;
$rendimA->vol_prod3 = $lista->vol_prod3;
$rendimA->save();
}
The fields that I have to fill are in the rendim_actual table and are the following:
codigo = concat(fundo, rodal) from $var
edad= from $var
densidad = from $var
vol_prod1 to n (actually there are 36 but as an example just leave 3) from $var
in terms of time insert by Eloquent takes about 15 minutes, I hope you can help me, ty
I am using laravel-5.8 and postgresql
I don't have much experience dealing with large databases, but in your solution you will be making 120k separate inserts, which will not be efficient.
If the records in your $var array are already in the correct format from your table you can try using the query builder's insert method.
// Not certain what your table name is
DB::table('rendim_actual')->insert($var);
DB::commit();
If the $var array becomes soo big that you cannot insert all data in one insert, you can look into this SO Question about chunking inserts.
What you are currently doing is running an insert query for each RendimActual. What you should be doing is bulk insert via ::insert()
insert()
This will insert 1 query with 120K values
$insert = [];
foreach ($var as $lista) {
$insert[] = [
'codigo' => $lista->fundo . $lista->rodal,
'edad' => $lista->edad,
'densidad' => $lista->densidad,
'vol_prod1' => $lista->vol_prod1,
'vol_prod2' => $lista->vol_prod2,
'vol_prod3' => $lista->vol_prod3
];
}
RendimActual::insert($insert);
chunk()
Since you are inserting 120K values inside 1 query, there's a chance of consuming a lot of memory. So, it better to chunk() the data if 2000 rows and insert those 2K first. Even though you will be running 120K/2K = 60 queries ... at least this way each query will not be consuming memory compared to 1 big (120K) insert query.
foreach (array_chunk($insert, 2000) as $inst) {
RendimActual::insert($inst);
}
Keep me posted in the comments below. Cheers!

Insert 60000 rows Mysql from PHP

I have a MySQL database with a backend: PHP.
In one table I have to insert 60,000 rows.
We made a query into my PHP that returns 1,000 rows. For each rows we have to insert 60 rows. We thought make a loop but we don't know if is the best practices that way.
The part of the code that insert the data is:
$turnos = $db->query("SELECT * FROM turno t
WHERE t.canchaId = :cancha
AND t.fecha BETWEEN :fechaInicio AND :fechaFin
AND t.nombre LIKE :cadena
ORDER BY t.fecha,t.hora ASC",
array("cancha" => $cancha["idCancha"], "fechaInicio" => $fechaInicio, "fechaFin" => $fechaFin, "cadena" => "%turno fijo%"));
foreach($turnos as $turno) {
//turnos have 1000 rows
$fecha = date_create($turno["fecha"]);
date_add($fecha, date_interval_create_from_date_string('7 days'));
$anioAuxiliar = 2017;
while(2017 == $anioAuxiliar){
//60 times
$data1 = turno[data1];
$data2 = turno[data2];
...
$fechaAGuardar = (String) $fecha->format('Y-m-d');
$result = $db->query("INSERT INTO turno(fechaAGuardar, data2, data3, data4, data5, data6, data7, data8) VALUES(:fechaAGuardar, :data2, :data3, :data4, :data5, :data6, :data7, :data8)",
array("fechaAGuardar" => $fechaAGuardar, "data2" => $data2, "data3" => $data3, "data4" => $data4, "data5" => $data5, "data6" => $data6, "data7" => $data7, "data8" => $data8));
date_add($fecha, date_interval_create_from_date_string('7 days'));
$anioAuxiliar = (int) $fecha->format("Y");
}
$cantidad_turnos = $cantidad_turnos + 1;
}
This php is into a hosting with phpmyadmin.
So my questions are:
This is the best way to insert 60,000 rows?
Shall we considerer take into account another constraint? (eg: phpmyadmin don't allow you insert that amount of rows)
Thanks for helping me, Any suggestions are welcome
//EDIT//
The inserts data change, we have to insert datetime, and for each loop we have to add 7 day the last date inserted. So we can't use insert with select
As a bunch of fellows described in the comments, INSERT/SELECT is the way to go if this data is in the same server/database. There's no need to use PHP at all. Your year comment can be handled with DATE_ADD.
Anyway, if there is any other requirement and you can't use PHP, consider using Bulk Data Loading.
Analysing your code, the MOST IMPORTANT TIP would be: don't use multiple INSERT INTO TABLE expressions. Each INSERT INTO will cause a round trip do the database and things will get really slow. Instead of it, concat multiple values with one INSERT INTO (example from the link):
INSERT INTO yourtable VALUES (1,2), (5,5), ...;
Good luck!

display two second last value from database

Good Morning....
I am using php MySQL to store the students marks in database....
my database table is like this...
25 63 96 85 65
56 56 96 36 23
56 78 98 45 12
Now I am trying to display last two values from database table and wants to show anywhere else on my website...
I am using below code...
<?php
$q = "SELECT CONCAT (a) FROM record ORDER BY id DESC
LIMIT 1;";
$result = mysql_query($q);
$data = mysql_fetch_array($result);
echo $data[0];
?>
The above code display only last value....which is 12 above shown table...
I want to display both 45 and 12 from above shown table like this...
{45}==>{12}
Can anybody correct my code....
Thanks...
As Saitama pointed out in the comments, the mysql_* functions are deprecated. Best to use PDO or the mysqli_* functions as they will be supported in the future.
I mention it at the start because it's hugely important for both security and ongoing support.
That being said, you need to do two things in order to get your desired result. First, your query must return more than 1 value, so the LIMIT must be increased as sgeddes pointed out, and then you must display both values, not just the first value in the list of returned values (which is what $data[0] is doing now - just returning the first item in the array).
Try something like this:
<?php
$q = "SELECT CONCAT (a) FROM record ORDER BY id DESC
LIMIT 2;";
$result = mysql_query($q);
$data = mysql_fetch_array($result);
echo "{" . $data[1] . "}==>{" . $data[0] . "}"; //prints: "{45}==>{12}"
?>
Essentially, since $data is an array, you need to convert it into a string. I did this above by referencing its elements, but that is a fairly crude way to do it. If for example there is only 1 value in the database, trying to echo $data[1] would throw a notice because there is no second value in the array.
implode is a handy method to use because you can convert an array into a string and use a value, like a comma, to glue the values together.
echo implode(", ", $data); //prints "12, 45" (12 first because it is the first item in the array)
If you're not sure a key exists in an array, you can use the empty function, which checks if the key is set (isset), and if it has a non-falsey value.
if (empty($data[0] == false) {
echo $data[0];
}
if (empty($data[1] == false) {
echo $data[1];
}
Documentation:
PDO documentation: http://php.net/manual/en/book.pdo.php
mysqli_* documentation: http://php.net/manual/en/book.mysqli.php
implode documentation: http://php.net/manual/en/function.implode.php
isset documentation:http://php.net/manual/en/function.isset.php
empty documentation:http://php.net/manual/en/function.empty.php
$query="SELECT CONCAT (a) FROM record ORDER BY id DESC
LIMIT 2";
Order by DESC Limit 2 get Last two records from Database.

htmlentities function breaking a while loop

I have a piece of code which is driving me crazy please help!
Basically I have result set from a database returning 3 rows of data, the data in the field I'm interested in is as below:
row 1 - "the Retention Release Date;"
row 2 - "where applicable, any later due date for Retention release under clause 4·15·2·3; or"
row 3 - "the date of issue of the Contractor's statement under clause 4·6·2 or, in default, the last date for issue of that statement."
The array is $result_set and the associative key is ['subsubclausedesc'] so the code I am running is:
while($result_set = $database->fetch_array($result))
{
echo htmlentities($result_set['subsubclausedesc']);
}
The problem I am having is that only the 1st row is being returned to the screen, if I echo without htmlentities I get all 3 rows, what am I doing wrong?
You can try this with stripslashes
while($result_set = $database->fetch_array($result))
{
echo htmlentities(stripslashes($result_set['subsubclausedesc']));
}

Echo / Output 0 (zero) is not working

I'm running a query to get the total sum of some hours from a database table to show in a PDF file but for some strange reason it won't echo 0 (zero).
$query = mysql_query("SELECT id, SUM(hours_night), SUM(hours_days) FROM table WHERE invoiceID='".mysql_real_escape_string($invoiceID)."'") or die(mysql_error());
$result = mysql_num_rows($query);
$totalhours_night = 0;
while ($fetch = mysql_fetch_assoc($query)) {
$totalhours_night += $fetch['SUM(hours_night)'];
}
$html_output = "Some html and tables markup... " . $totalhours_night . "";
The output of the html works fine, thats not the problem.. but the problem is it won't output 0 (zero) for some reason. If the hour result is actualy something like 1 or 5 or whatever it outputs the totalhours fine, but i need it to output 0 if there are no hours.
Because it looks strange to ouput nothing if there are no hours, i need to display a 0 zero since this looks more good.
BTW, if i for example put number_format($totalhours_night, 2); it does display 0.00, but i need it to be just 0.
Three things:
Your SQL query is wrong, you can't display id and SUM(..) unless you use GROUP BY id (Which kid of loses the idea if id is unique)
If you use SUM(..) give it an alias like SUM(..) AS alias1, and later in the PHP refer to alias1.
If this is not the reason, try var_dump($fetch['alias1']); and look at what you really get back. (And post your findings here so we can give you further help)
Treat integer as string like this-
echo (string)$totalhours_night;

Categories