I was wondering if someone could help me please.
I have the following two tables, positions and polygons.
positions:
----------------------------------------------
| positionID | name | information
----------------------------------------------
| 1 | Southampton | text here
| 2 | London | text here
.
polygons:
-------------------------------------------------------------------
| polygonID | positionID | lat | lon
-------------------------------------------------------------------
| 1 | 1 | 434343.034343 | -43.4343434
| 2 | 1 | 343343.034343 | -43.4343434
| 3 | 1 | 434343.034343 | -54.4343434
I want to join the two tables and output them as an array in the following format.
$positions = array(
array( positionID => 1,
name => 'Southampton',
information => 'text here',
polys => array( array( Lat => 54.54299483853406,
Lng => -6.5224456787109375,
),
array( Lat => 54.648809788121866,
Lng => -6.405029296875,
),
array( Lat => 54.54020652089137,
Lng => -6.39129638671875,
),
),
),
);
I have wrote the following join statement however I'm really stuck on the next step.
SELECT * FROM (`positions`) LEFT JOIN `polygons` ON `positions`.`positionID` = `positions`.`positions`
The lat/lon data from the joins must be stored on the 'polys' key in the array.
Any help or advice would be much appreciated.
Thanks a million
If you have more than one polygonID per positionID, you going to fetch a lot of copies of positions.
I recommend to do 2 queries instead:
$positions = array();
$query_1 = "SELECT * FROM positions";
$query_2 = "SELECT * FROM polygons";
$resource_1 = mysql_query($query_1);
while($position = mysql_fetch_assoc($resource_1))
{
$positions[$position['positionID']] = $position;
$positions[$position['positionID']]['polys'] = array();
}
$resource_2 = mysql_query($query_2);
while($polygon = mysql_fetch_assoc($resource_2))
{
$positions[$polygon['positionID']]['polys'][$polygon['polygonID']]['Lat'] = $polygon['lat'];
$positions[$polygon['positionID']]['polys'][$polygon['polygonID']]['Lon'] = $polygon['lon'];
}
(Sorry for using deprecated functions like mysql_query in my exemple)
You only need one query, but you still need to do some processing with the result in PHP:
$sql = "SELECT * FROM positions
LEFT JOIN polygons ON positions.positionID = polygons.positionID";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
$positions = array();
while ($row = mysql_fetch_assoc($result)) {
if (!isset($positions[$row['name']])) {
$positions[$row['name']] = array(
'positionID' => $row['positionID'],
'information' => $row['information'],
'polys' => array()
);
}
$positions[$row['name']]['polys'][] = array(
'lat' => $row['lat'],
'lon' => $row['lon']
);
}
print_r($positions);
}
This will also return positions which don't actually have any polygon information. To prevent that, simply change the LEFT JOIN to JOIN.
As for which is most efficient, I'm afraid I don't know the answer to that. Best bet is to benchmark both this method and the one advised by Puggan Se if you can.
Related
alright best way for me to explain is by giving an example
Table 1
ID | name | class
-------------------------
1 | first name | a
2 | second name | b
Table 2
ID | name_id | meta_key | meta_value |
-------------------------------------------------------
1 | 1 | image | someImage.jpg |
2 | 1 | description | very long description |
3 | 2 | image | someImage_2.jpg |
4 | 2 | description | very long description 2 |
I am trying to select name and class from Table 1, and also all the records from Table 2 that has the same name_id as ID (in Table 1).
Here is the query i have now:
SELECT
table1.name,
table1.class,
table2.name_id,
table2.meta_key,
table2.meta_value
FROM
table1
LEFT JOIN
table2 ON ( table1.ID = table2.name_id )
WHERE
table1.ID = '2'
This works and return an array with as many elements as the Table 2 entries that has name_id = 2
Is there a way to return an array with 1 the result from first table, and another array with results from the second table ?
Update:
The ideal results will be:
$result['table1'][0] = array('name' => 'second name',
'class' => 'b')
$result['table2'][0] = array('name_id' => 2,
'meta_key' => 'image',
'meta_value' => 'someImage_2.jpg')
$result['table2'][1] = array('name_id' => 2,
'meta_key' => 'description',
'meta_value' => 'very long description 2')
hopes that makes sense.
I'd split the result array AFTER fetching it from the database...
//Assuming your result-set is assigned to $result:
$table1_keys = array('id', 'name', 'class');
$table2_keys = array('id', 'name_id', 'meta_key', 'meta_value');
$table1_results = array();
$table2_results = array();
foreach($result as $key => $val) {
if(in_array($key, $table1_keys)) {
$table1_results[] = $val;
}
if(in_array($key, $table2_keys)) {
$table2_results[] = $val;
}
}
After this, your result-set should be split into two arrays: $table1_results and $table2_results.
Hope this helps you.
I don't believe there's a way to do it in SQL but I'd label each table so it can be done generically in PHP.
SELECT
':table1',
table1.name,
table1.class,
':table2',
table2.name_id,
table2.meta_key,
table2.meta_value
FROM ...
Although personally I'd just do this.
SELECT 'table1', table1.*, ':table2', table2.*
FROM ...
That makes it easier to duplicate entire rows between client and server and reduces maintenance when you decide to add a new field.
However in your query you are duplicating table1 for each row returned so perhaps this would be better.
SELECT
table1.*,
table2a.meta_value AS image,
table2b.meta_value AS description
FROM
table1
LEFT JOIN
table2 AS table2a ON ( table1.ID = table2a.name_id AND table2a.meta_key = 'image' )
LEFT JOIN
table2 AS table2b ON ( table1.ID = table2b.name_id AND table2b.meta_key = 'description' )
WHERE
table1.ID = '2'
I have two mysql database table, one is for posts and other is for comments.
Post table
+----+-------+
| ID | texts |
+----+-------+
| 1 | abc |
| 2 | xyz |
+----+-------+
And comments table
+----+--------+-------+
| ID | postid | texts |
+----+--------+-------+
| 1 | 1 | abc1 |
| 2 | 1 | abc2 |
| 3 | 1 | abc3 |
| 4 | 2 | xyz1 |
| 5 | 2 | xyz2 |
+----+--------+-------+
Now, How to get posts with bare minimum mysql query requests, so that output is like,
$data = array(
0 => array(
ID => 1,
texts => abc,
comments => array(
0 => array(
ID => 1,
texts => abc1
)
1 => array(
ID => 2,
texts => abc2
)
2 => array(
ID => 3,
texts => abc3
)
)
)
1 => array(
ID => 2,
texts => xyz,
comments => array(
0 => array(
ID => 4,
texts => xyz1
)
1 => array(
ID => 5,
texts => xyz2
)
)
)
)
How about
SELECT *
FROM Post p LEFT JOIN
Comments c ON p.ID = c.postID
It will be helpful if you can provide code to put results in array
Let me first recommend a better multidimensional array that will be easier to work with.
Array Format:
$data = array(
post.ID => array(
"texts" => post.texts,
"comments" => array(
comments.ID => comments.texts,
),
),
);
The above format will be easier to work with especially for direct access into the array and also for the foreach loop.
Now for assigning the data from the MySQL result into the array using mysqli_* functions and a while loop do the following:
//connect to mysql database
$link = $mysqli_connect("localhost","your_user","your_password","your_database");
//form mysql query
$query = "
SELECT
post.ID AS post_id,
post.texts AS post_texts,
comments.ID AS comments_id,
comments.texts AS comments_texts
FROM
post
LEFT JOIN comments ON (comments.postid = post.ID)
WHERE
posts.ID < 10
";
//run mysql query and return results
$mysqli_result = mysqli_query($link,$query);
//define empty $data array
$data = array();
//loop through result sets fetching string array with each result row
while($row = mysqli_fetch_array($mysqli_result)){
//set the post text if not already set
if(!isset($data[$row["post_id"]]["texts"])){
$data[$row["post_id"]]["texts"] = $row["post_texts"];
}
//set the comments data if not NULL otherwise set comments to empty array to maintain structure
if(!empty($row["comments_id"])){
$data[$row["post_id"]]["comments"][$row["comments_id"]] = $row["comments_texts"];
} else {
$data[$row["post_id"]]["comments"] = array();
}
}
//free the results set
mysqli_free_result($mysqli_result);
//close connection to mysql database
mysqli_close($link);
//print out the post text with the id of 1 with two line breaks
//be careful using this method unless you are sure that post with id of 1 exists or first check if(isset($data["1"])){...}
print $data["1"]["texts"]."<br /><br />";
//loop through all of the comments for a particular post with id of 1
foreach($data["1"]["comments"] as $key => $value){
//print out the comment id with a line break
print "Comment ID: ".$key."<br />";
//print out the comments texts with two line breaks
print "Comment: ".$value."<br /><br />";
}
//loop through and print all the post texts and how many comments exist for the post
foreach($data as $key => $value){
//print the post ID with a line break
print "Post ID: ".$key."<br />";
//print the post texts with a line break
print "Post: ".$value["texts"]."<br />";
//count the number of comments
$num_comments = count($value["comments"]);
//get correct plural form of noun
($num_comments==1) ? $comments = "comment" : $comments = "comments";
//print the number of comments for the post with two line breaks
print $num_comments." ".$comments." for this post.<br /><br />";
}
I'm working on a Bubble Chart using Highcharts. Here's a sample of my data:
name | price | quantity | count
--------+-------+----------+-------
Female | 2 | 3 | 5
Female | 3 | 12 | 10
Female | 5 | 6 | 15
Female | 1 | 7 | 25
Male | 3 | 5 | 7
Male | 2 | 9 | 11
Male | 5 | 7 | 23
Male | 4 | 4 | 14
I'm using PHP to query the data and encode to JSON:
$query = "SELECT name, price, quantity, count FROM sales WHERE id = $1";
$result = pg_prepare($db, "report", $query);
$result = pg_execute($db, "report", array($ID));
while ($row = pg_fetch_array($result, NULL, PGSQL_ASSOC))
{
$response['xdata'][$row['name']]['x'][] = $row['price'];
$response['xdata'][$row['name']]['y'][] = $row['quantity'];
$response['xdata'][$row['name']]['radius'][] = $row['count'];
}
echo json_encode($response);
However, the desired JSON format is as follows in order to properly plot the graph:
series: [{
name: 'Female',
marker:{
symbol:'circle',
fillColor:'rgba(24,90,169,.5)',
lineColor:'rgba(24,90,169,.75)',
lineWidth:1,
color:'rgba(24,90,169,1)',
states:{
hover:{
enabled:false
}
}
},
data: [{x:2,y:3,marker:{radius:5}},
{x:3,y:12,marker:{radius:10}},
{x:5,y:6,marker:{radius:15}},
{x:1,y:7,marker:{radius:25}}]
},{
name: 'Male',
marker:{
symbol:'circle',
fillColor:'rgba(238,46,47,.5)',
lineColor:'rgba(238,46,47,.75)',
lineWidth:1,
color:'rgba(238,46,47,1)',
states:{
hover:{
enabled:false
}
}
},
data: [{x:3,y:5,marker:{radius:7}},
{x:2,y:9,marker:{radius:11}},
{x:5,y:7,marker:{radius:23}},
{x:4,y:4,marker:{radius:14}}]
}]
My question is, how can I correctly process $query in PHP to get the desired JSON format as above and pass it to series through something like optionsBubble.series = data.xdata? Thanks a lot!
You'd first have to build the non-db-related parts into your PHP structure, e.g.
$data = array(
0 => array(
'name' => 'Female',
'marker' => array (
'symbol': 'circle'
etc....),
'data' => array() // database insertion occurs here
),
1 => array(
'name' => 'Male',
etc...
)
);
$locations = array('Female' => 0, 'Male' => 1, etc...) // reverse map your 'name' fields
while(...) {
$data[$locations[$row['name']]][data]['x'][] = $row['price'];
$data[$locations[$row['name']]][data]['y'][] = $row['quantity'];
^^^^^^^^^^^^^^^^^^^^^^^^--- reverse lookup to get right array index for 'name'
}
First I'm going to recommend you take a look at your SQL query, especially the part of WHERE id=$1. If I'm not mistaken (and on this I'm fairly sure.) your query is going to return one (1) row not many like what you probably want. I would recommend removing the WHERE clause and see if that solves your problem.
If not drop me a line and I'll see what else I see and we can go from there.
I have a table "exercise_results". People put in their results at the beginning and then two months later put in their results to see how much they improved. Their beginning set has the exercise_type_id of "1" and the end set has the exercise_type_id of "2".
I need a way to display this out into a HTML table that looks like this:
a foreach loop, but that's with single rows. I'm having trouble combining two rows into one. I think this may be as simple as some kind of MySQL join? We identify each person by their person_unique_id.
Here are my fields:
id | person_unique_id | person_name | exercise_type_id | mile_running_time | bench_press_weight_lbs | squat_weight_lbs | date_of_exercise_performed
Sample rows:
1 | J123 | John Smith | 1 | 8 | 200 | 300 | 2010-03-20
2 | J123 | John Smith | 2 | 7 | 250 | 400 | 2010-05-20
3 | X584 | Jane Doe | 1 | 10 | 100 | 200 | 2010-03-20
4 | X584 | Jane Doe | 2 | 8 | 150 | 220 | 2010-05-20
I've tried a few solutions but I'm lost. Any help would be great. Thanks!
EDIT:
In response to the comment below, I would hope for some data like:
array 0 =>
array
'Exercise' =>
array
'person_unique_id' => string 'J123'
'person_name' => string 'John Smith'
'begin_mile_running_time' => string '8'
'end_mile_running_time' => string '7'
1 =>
array
'Exercise' =>
array
'person_unique_id' => string 'X584'
'person_name' => string 'Jane Doe'
'begin_mile_running_time' => string '10'
'end_mile_running_time' => string '8'
You can use GROUP_CONCAT() to get a two rows result like this:
SELECT person_unique_id, person_name,
group_concat( mile_running_time ) AS miles,
group_concat( bench_press_weight_lbs ) AS bench,
GROUP_CONCAT( squat_weight_lbs ) AS squat
FROM exercise_result
GROUP BY person_unique_id
Your result will be like:
J123 | John Smith | 8,7 | 200,250 | 300,400
X584 | Jane Doe | 10,8 | 100,150 | 200,220
And then you can use php explode with the result fields to get the results for each type.
Extract the whole table, or whichever rows are interesting to you, sort on person id, compare person id of each row with the next to see if there is a result to print for all columns in your HTML table. If not, jump to the next and leave the fields blank(or some other solution, maybe ignore persons who have not filled in both fields?).
My PHP skills are limited, so no code example.
$query = mysql_query("select ...your data");
while ($row = mysql_fetch_assoc ($query) ) {
if ($row['exercise_type_id']==1)
$exe1[]=$row;
else
$exe2[]=$row;
}
print_r($exe1);
print_r($exe2);
from what I've understood
edit:
try this
$query = mysql_query("select ...your data");
while ($row = mysql_fetch_assoc ($query) ) {
$rows[]=array('Exercise'=>$row);
}
print_r($rows);
If you are ordering on person_unique_id then exercise_type_id, you can do this. If you have two rows for everyone, you can leave out the if (only use the else):
for( $i = 0; $i < count($exercise_results); $i++ )
{
$first = $exercise_results[$i];
if( !isset($exercise_results[$i+1])
|| $first['person_unique_id'] != $exercise_results[$i+1]['person_unique_id' ) {
$second = array(
'person_name'=>$other['person_name'],
'mile_running_time' => null // fill in the rest with defaults (like null)
);
} else {
$second = $exercise_results[$i+1];
$i++; // skip ahead one, since you've already used the second result.
}
// perform your normal printing, but use $beginning and $end to get the respective results
}
Please help me to create an array from a field of my DB. That field has records separated by comma. Below is the illustration:
ID | article_title_fld | article_tags_fld |
----------------------------------------------------------------------
1 | Learn PHP | PHP, coding, scripting |
3 | Javascript Tutorial | Javascript, scripting, tutorial |
4 | Styling with CSS | CSS, tutorial, web design |
I want to collect all records in the article_tags_fld then put it into 1 array. Perhaps I named it $array1, and the print out as below:
Array
(
[0] => PHP
[1] => coding
[2] => scripting
[3] => Javascript
[4] => scripting
[5] => tutorial
[6] => CSS
[7] => tutorial
[8] => web design
)
$array1 = array();
$result = mysql_query("SELECT article_tags_fld FROM MY_TABLE");
while ($row = mysql_fetch_assoc($result)) {
$array1 = array_merge($array1, array_map('trim', explode(",", $row['article_tags_fld'])));
}
explode will split a string by a delimiter.
array_merge will combine two arrays.
array_map will apply trim to all elements.
trim will remove any white space on either side of your tags.
Actually, I would normalize the table into multiple tables first.
articles
article_ID | article_title_fld |
----------------------------------------
1 | Learn PHP |
3 | Javascript Tutorial |
4 | Styling with CSS |
tags
tag_ID | tag_title_fld |
------------------------
1 | PHP |
2 | coding |
3 | scripting |
4 | Javascript |
5 | tutorial |
6 | CSS |
7 | web design |
article_tags
article_ID | tag_ID |
---------------------
1 | 1 |
1 | 2 |
1 | 3 |
3 | 4 |
3 | 3 |
3 | 5 |
4 | 6 |
4 | 5 |
4 | 7 |
and then in the PHP
$array1 = array();
$result = mysql_query("
SELECT tag_title_fld
FROM tags
JOIN articles_tags USING(tag_ID)
ORDER BY article.article_ID
");
foreach($result as $row) {
$array1[] = $row['tag_title_fld'];
// With count. See below for the query it goes with
// $array2 = array();
// $array2['tag'] = $row['tag_title_fld'];
// $array2['count'] = $row['tag_count'];
// $array1[] = $array2;
}
Of course, if you just wanted a list of the tags without duplicates, you'd use this query instead.
SELECT tag_title_fld
FROM tags
and if you wanted them with a count of how often they're used:
SELECT tag_title_fld, COUNT(*) AS tag_count
FROM tags
JOIN articles_tags USING(tag_ID)
GROUP BY tag_title_fld
UPDATED
you can do also this way by using mysql_fetch_Array
$array1 = array();
$result = mysql_query("SELECT ID , article_tags_fld FROM my_table");
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$array1[] = $row['article_tags_fld'];
// OR
// $array1[] = $row[1];
}
ADDED:
in one line:
// use this version to behave as in your example..
$array1 = array_map('trim',explode(',',implode(',',$array1)));
// use this version with array_unique for a non duplicate way...
$array1 = array_unique(array_map('trim',explode(',',implode(',',$array1))));
DISPLAY:
print_r( $array1 );
Array
(
[0] => PHP
[1] => coding
[2] => scripting
[3] => Javascript
[4] => scripting
[5] => tutorial
[6] => CSS
[7] => tutorial
[8] => web design
)
This should output everything.
$pdo = new PDO( /* CONNECTION */ );
$stmt = $pdo->query( 'SELECT article_tags_fld FROM TABLENAME' );
function mapFunc( $row ){ return explode( ',', $row[ 0 ] ) }
$all = array();
foreach( array_map( 'mapFunc', $stmt->fetchAll() ) as $row )
{
$all = array_merge( $all, $row );
}
// $all now holds all of the values.
You should normalize your database table so that you don't have comma-separated values in your rows.
mysql_ functions should no longer be used, so I'll demonstrate mysqli's object-oriented syntax.
If your database values are consistently comma-space separated, then explode() is fine. If you might have leading or trailing spaces in your article_tags_fld values, then you can TRIM() that in your SQL. If you might not have spaces after each comma, then you can explode the strings with preg_split() using a pattern like /, */.
The result set object from a mysqli query is iterable by foreach(), so you can safely avoid making iterated fetch() calls to access the column of data.
By pushing the exploded values with the spread operator (...), the result array will be flat.
If you want to remove duplicate values from the result, you can call array_unique() on the result array after the loop is finished.
Modernized Code: (Full MYSQL + PHP Demo)
$result = [];
foreach ($mysqli->query("SELECT article_tags_fld FROM MY_TABLE") as $row) {
array_push($result, ...explode(', ', $row['article_tags_fld']));
}
var_export(array_unique($result));