JOIN in an associative array instead of separated records - php

Table stores
id name date
1 foo 2011-06-15 15:10:34
2 bar 2011-07-02 16:45:18
Table locations
storeid zipcode latitude longitude
1 90001 xxxxx xxxxx
1 45802 xxxxx xxxxx
2 32843 xxxxx xxxxx
How can i produce an associative array that contains a key called locations which is an array of all locations of a store?
My current SQL ( which separate each location in a record ):
SELECT stores.*, locations.* FROM locations INNER JOIN stores ON stores.id = locations.storeid
Example of what i want:
array(
[0] => array(
"id" => 1,
"name" => "foo",
"locations" => array(
[0] => array(
"zipcode" => 90001,
"latitude" => -45.48513,
"longitude" => 82.12432
)
[1] => array(
"zipcode" => 42802,
"latitude" => -31.48513,
"longitude" => 77.12432
)
)
)
)
and so on for other stores...
Thanks

So you can't extract the data in one query because SQL normally works per row and hasn't got data structure like PHP arrays. You can't nest the records using JOIN. That's why you'll have to do it with with separate queries in a PHP loop. Like so:
$query = "SELECT s.id,s.name FROM stores AS s";
$result = mysql_query($query);
$data = array();
while($row = mysql_fetch_assoc( $result )) {
$data[] = $row['id'];
$data[] = $row['name'];
$query2 = "SELECT l.zipcode, l.latitude, l.longitude FROM locations AS l WHERE storeid=".$row['id'];
$result2 = mysql_query($query2);
while($row2 = mysql_fetch_assoc( $result )) {
$data['locations']['zipcode'] = $row2['zipcode'];
$data['locations']['latitude'] = $row2['latitude'];
$data['locations']['longitude'] = $row2['longitude'];
}
}
Otherwise you can grab all results with JOIN and do as follows:
$query = "SELECT * FROM stores AS s
LEFT JOIN locations AS l
ON s.id = l.storesid";
$result = mysql_query($query);
$data = array();
while($row = mysql_fetch_assoc( $result )) {
$data[$row[id]]['id'] = $row['id'];
$data[$row[id]]['name'] = $row['name'];
$data[$row[id]]['locations'][] = array($row['zipcode'], $row['latitude'], $row['longitude']);
}
But this will make the main array's index to be set not sequential starting from 0 but each index will be equal to the ID of the "store" item

Related

SQL query to take avg of column data into JSON for google pie chart in PHP

I need to create a SQL query and the PHP code to enter this data into JSON format for a pie chart using Google Charts API.
+--------+---------+---------+---------+
| City | P1 | P10 | P25 |
+--------+---------+---------+---------+
|Dubai | 45| 135| 136|
|SanDiego| 23| 34| 45|
|SanFran | 37| 39| 28|
+--------+---------+---------+---------+
This is the query I have already tried:
<?php
$rows2 = array();
$table2 = array();
$query2 = 'SELECT AVG(`P1`) AS avg_p1, AVG(`P10`) AS avg_p10, AVG(`P25`) (SELECT `P1`, `P10`, `P25`
FROM `INFORMATION_SCHEMA`.`COLUMNS` AS pmname
WHERE `TABLE_SCHEMA`='g1109689'
AND `TABLE_NAME`='realtime') AS avg_p25 FROM `realtime` WHERE `City`="Dubai"';
$result2 = mysqli_query($conn, $query2);
$table2['cols'] = array(
array(
'label' => 'PM Type',
'type' => 'string'
),
array(
'label' => 'PM Number',
'type' => 'number'
)
);
while($row2 = mysqli_fetch_array($result2))
{
$sub_array2 = array();
$sub_array2[] = array(
"v" => $row2["avg_p1"]
);
$sub_array2[] = array(
"v" => $row2["avg_p10"]
);
$sub_array[] = array(
"v" => $row2["avg_p25"]
);
$rows2[] = array(
"c" => $sub_array2
);
}
$table2['rows'] = $rows2;
echo $jsonTable2;
?>
I want the categories for the pie chart to be the averages of P1, P10, P25, respectively. So how do I create a SQL statement to select the averages and the name of the columns and how do I put that into a JSON table? Thanks!
I am guessing that you want average rowwise i.e. adding (p1+p10+p25)/3 for every city and not columnwise. So you can try the below query-
select city,(tablename.p1 + tablename.p10 + tablename.p25) / 3 as average from tablename
If you want to calculate avg columnwise for everycity you can use avg() method of sql.
select city, avg(p1),avg(p10),avg(p25) from tablename;
PS: you will only get name of one city if you use avg() function

PDO: group a property instead of duplicate lines

Good morning,
I have a request that return me several information for a reservation and each reservation can be linked to several room.
Is it possible to have an array of room instead of duplicate the line each time they are multiple rooms for a reservation.
What I want:
[
idReservation1 => [
"client_name" => "kévin titi",
"checkin" => "2017-08-08",
"d_checkout" => "2017-08-10",
"email" => "titi#gmail.com",
room_id => [1,2,3,9]//here I want an array
],
idReservation2 => [
"client_name" => "firstname lastname",
"checkin" => "2017-08-18",
"d_checkout" => "2017-08-20",
"email" => "toto#gmail.com",
"room_id" => [1,12,13,9]//here I want an array
]
]
if the idReservation is not the key does not matter, the important here is to have an array for room_id
I have looked all PDO fetch modes but they don't seems to match to my problem.
My request:
$prep = $this->pdo->prepare("
SELECT re.id as resId, re.client_name, re.d_checkin, re.d_checkout, re.mail, ro_re.room_id as room
FROM Reservation re
JOIN Room_Reservation ro_re ON ro_re.reservation_id = re.id
WHERE re.confirmed = false
");
Thanks
Assuming that you are working with MySql: the solution using GROUP_CONCAT function(to group room ids for each reservation):
$stmt = $this->pdo->prepare("
SELECT
re.id as resId, re.client_name, re.d_checkin, re.d_checkout, re.mail,
GROUP_CONCAT(ro_re.room_id SEPARATOR ',') AS room_ids
FROM
Reservation re
INNER JOIN Room_Reservation ro_re ON ro_re.reservation_id = re.id
WHERE re.confirmed = false
GROUP BY re.id
");
$stmt->execute();
// `room_ids` column will contain a string like "1,2,3,9"
$result = [];
foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
$row['room_ids'] = explode(',', $row['room_ids']); // converting string with room ids into array
$result[] = $row;
}

Array joining using an id as reference

I have 2 tables. The first table is an equipment table. A query from this table looks like this:
id name user_id
-----------------------
1 equip1 1001
2 equip2 1002
The seconde table is an users table. A query from this table looks like this:
id username
--------------
1001 user1
1002 user2
I want to achieve something like this:
id name user_id username
-----------------------------------
1 equip1 1001 user1
2 equip2 1002 user2
Is there a way to join both arrays like doing a join query? I can't use JOIN in my query, because the tables are on different databases (I know there is a way to do JOIN on different databases, but I'm not allowed to use that).
EDIT:
I'm adding the structure of these arrays.
$equipment = array(
[0] => array(
['id'] => 1,
['name'] => 'equip1',
['user_id'] => 1001
),
[1] => array(
['id'] => 2,
['name'] => 'equip2',
['user_id'] => 1002
)
);
$users= array(
[0] => array(
['id'] => 1001,
['username'] => 'user1'
),
[1] => array(
['id'] => 1002,
['username'] => 'user2'
)
);
You would likely have to join the queries yourself. I don't believe there is a built in function (not counting walk or map with a callback). This is what I would do
//empty array for indexing users under their id for faster loopups
$users = array();
//loop over the users result
foreach($usersResult as $row){
//index users under their id.
$users[$row['id']] = $row['username'];
}
//now loop over the equipment to join the arrays together
foreach($equipmentResult as $key=>$row){
//add the username column
$row['username'] = isset($users[$row['user_id']])?$users[$row['user_id']]:null;
//save back into the equipment row
$equipmentResult[$key] = $row;
}
//display
print_r($equipmentResult);
This could easily be turned into a function where you pass arguments that would build the "ON" portion for the column names.
Edit: Made it a function.
<?php
/**
* Joins two arrays as if they were joined in a query
* #param Array $arrayA The base (left) array to join into
* #param Array $arrayB The right array to join into A
* #param String $colA The column name to join on for arrayA
* #param String $colB [optional] The column name to join on for arrayB. If
* blank, then it is assumed the same column name as colA
* #param boolean $leftJoin [optional] Should this be a left join and include rows
* from A where no value exists in B?
* #return void
*/
function array_join($arrayA, $arrayB, $colA, $colB=null, $leftJoin=false){
//if no value was passed for colB, assume it is the same value as colA
if(is_null($colB)){
$colB = $colA;
}
//output data
$out = array();
//create an index for array B for faster lookups
$idxB = array();
$colsB = array();
foreach($arrayB as $row){
//get the value from B
$valB = $row[$colB];
//if the column doesn't exist in the index, add it
if(!isset($idxB[$colB])){
$idxB[$colB] = array();
}
//index the value
$idxB[$valB][] = $row;
//store the known column to an array for use below
if(empty($colsB)){
$colsB = array_keys($row);
}
}
//loop over array A
foreach($arrayA as $rowA){
//get the value for the column
$valA = $rowA[$colA];
//does the value from A exist in B
$rowB = isset($idxB[$valA])?$idxB[$valA]:null;
//join the rows
//add blank columns if left join
if($leftJoin && is_null($rowB)){
$rowBJoin = array_combine($colsB, array_fill(0, count($colsB), null));
//add the row to our output
$out[] = $rowA + $rowBJoin;
} else {
//inner join or value is not null
//loop over all the rows from the B index that we are joining on
foreach($rowB as $rowBJoin){
//add the row to our output
$out[] = $rowA + $rowBJoin;
}
}
}
return $out;
}

MySQL Select FROM 3 tables AND put that in PHP array

Sorry for bad english and bad title!
I have the table "post"
id title
1 test Thread
2 hello
3 just
so have "tags"
tagid tagname
1 test
2 russia
3 new site
so have a post_tags
tagid postid
1 1
2 1
3 1
I need an array from var_dump next below:
$posts = array(
1 => array(
'title' => 'test Thread',
'tags' => array(
'test', 'russia', 'new site',
),
),
2 => array(
'title' => 'hello',
'tags' => NULL
),
3 => array(
'title' => 'just',
'tags' => NULL
),
)
I trying do it, but i getting not that what i want.
SELECT `post`.`id`, `post`.`title`, `tags`.`tagname` FROM `post`
LEFT JOIN `post_tags` ON `post_tags`.`tagid` = `post`.`id`
LEFT JOIN `tags` ON `post_tags`.`tagid` = `tags`.`tagid`
I getting in SQL next following:
id title tagname
1 test Thread test
1 test Thread russia
1 test Thread newsite
2 hello NULL
3 just NULL
PHP
$query = mysql_query("SELECT `post`.`id`, `post`.`title`, `tags`.`tagname` FROM `post`
LEFT JOIN `post_tags` ON `post_tags`.`tagid` = `post`.`id`
LEFT JOIN `tags` ON `post_tags`.`tagid` = `tags`.`tagid`");
$posts = array();
while ($row = mysql_fetch_assoc($query))
{
$posts[] = $row;
}
var_dump($posts);
Thank you!!!
The query is fine. You just need some logic in your loop:
while ($row = mysql_fetch_assoc($query))
{
if (isset($posts[$row['id']])) {
$posts[$row['id']]['tags'][] = $row['tagname'];
}
else {
$posts[$row['id']] = array(
'title' => $row['title'],
'tags' => $row['tagname'] === null ? null : array($row['tagname'])
);
}
}
If you have already seen a row with the same post id then all you want from the current row is the tag name (so add this to the "tags" array). If it's the first time a row with this post id is seen just add it to $posts, being a little careful to set "tags" to either null or an array with one element.
you cannot get a multi-dimensional arrays back from a mysql database. you must do your own post processing to the results if you want it in that form. Something like this maybe?
$posts = array();
while ($row = mysql_fetch_assoc($query))
{
if (!isset($posts[$row['id']])) {
$posts[$row['id']] = array();
$posts[$row['id']]['title'] = $row['title'];
$posts[$row['id']]['tags'] = array();
}
if ($row['tagname'] != null) $posts[$row['id']]['tags'][] = $row['tagname'];
}
Try this:
while ($row = mysql_fetch_assoc($query))
{
if( !isset( $posts[$row["id"]] ) ) {
$posts[ $row["id"] ] = array( "title" => $row["title"], "tags" => array() );
}
array_push( $posts[ $row["id"] ][ "tags" ], $row["tagname"] );
}
I can't debug it, so tell me if you get any errors

mysql fastest 2 table query

Situation: 2 tables, the first (Persons) storing person names and some other data, and the second (Phones) storing their phone numbers. There can be multiple phone numbers per person (thats why I am using separate tables in the first place).
Goal: Select everything so that in the end I'd have a php array like this:
array
(
'0' => array
(
'name' => 'John Smith'
// other values from table Persons...
'Phones' => array('0' => '12345', '1' => '324343') // from Phones table
),
'1' => array
(
'name' => 'Adam Smith'
// other values from table Persons...
'Phones' => array('0' => '645646', '1' => '304957389', '2' => '9435798') // from Phones table
)
);
ETC.
Phones.person_id = Persons.id
What would be the fastest way to do this? Fastest in a sense of program execution time, not the coding time. I could do simple JOIN but in this case I'd get many duplicate rows, i.e. for each phone I get all the data of the same person again and again in each row if you see what I mean. So I need to work on the array in PHP side. Maybe there's a better way?
One query. Check for typos:
$return = array();
$query = "SELECT pe.id, pe.name, ph.phone FROM Persons pe INNER JOIN phones ph ON pe.id = ph.person_id ";
$results = mysql_query($query);
if($results && mysql_num_rows($results)) {
while($row = mysql_fetch_assoc($results)) {
if(!$return[$row['id']]) {
$return[$row['id']] = array('name' => $row['name'], 'Phones' => array());
}
array_push($return[$row['id']]['Phones'], $row['phone']);
}
}
return $return;
Get the person first, and then query for each of the phone numbers.
$return = array();
$query = "SELECT `id`, `name` FROM `Persons`";
$person_results = mysql_query($query);
if($person_results && mysql_num_rows($person_results)) {
while($person_row = mysql_fetch_assoc($person_results)) {
$person = array();
$person['name'] = $person_row['name'];
$person['phone'] = array();
$query = "SELECT `number` FROM `Phones` WHERE `person_id` = '{$person_row['id']}'";
$phone_results = mysql_query($query);
if($phone_results && mysql_num_rows($phone_results)) {
while($phone_row = mysql_fetch_assoc($phone_results)) {
array_push($person['phone'], $phone_row['number']);
}
}
}
}
return $return;

Categories