Pagination from two SQL Tables with one query. Fastest Way - php

I have a simple Database:
Table 1: Object Table 2: Data
id | type | added object_id | key | value
------------------------ -----------------------------
1 | app | 2017 1 | name | ...
2 | app | 2017 2 | name | ...
3 | win | 2017 2 | version | ...
2 | dev_name | ...
2 | lang | ...
i created a simple pagination to show only 5 object from type apps with their infomation from the data table:
example code:
$sth = $dbh->prepare("SELECT * FROM object WHERE type = 'app' LIMIT 5");
$sth->execute;
$object = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach($object as $rows) {
$sth = $dbh->prepare("SELECT * FROM data WHERE id = $rows['id']");
$sth->execute;
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
echo $data['name'];
echo $data['version'];
echo $object['added'];
...
Is there a better way? because this is a very bad solution, i want to query only one time where i get an fetch array like this:
array(
// app with id = 1 in object table
[1] => array(
// data from the app with id = 1 in data table
[name] => ...
[version] => ...
[dev_name] => ...
[lang] => ...
// app with id = 2 in object table
[2] => array(
// data from the app with id = 2 in data table
[name] => ...
[version] => ...
[dev_name] => ...
[lang] => ...
...

one query:
SELECT * FROM object inner join data on data.id_object=object.id WHERE object.type = 'app' LIMIT 5
This query return information from two table with associate data.
I think that's what you want
If you want to group by id of the first table you can also execute this query
SELECT * FROM object inner join data on data.id_object=object.id WHERE object.type = 'app' group by object.id LIMIT 5
or
SELECT Distinct(object.id), object.type, .... FROM object inner join data on data.id_object=object.id WHERE object.type = 'app' LIMIT 5
Consider for string comparison use LIKE instead of =

Related

Providing the Custom Name to both Key and Value Pairs of an Array

I have a table named questions in the following form:
Table Name: questions
qn_id | question |
---------------------------------------------------------------
19 | What is your rating on your Team Work?
20 | What is your rating on your Skills?
21 | What is your rating on your Personal Quality?
I have another table named rating as shown below:
Table Name: rating
id | employee_id | question_id | self_score | supervisor_score
-----------------------------------------------------------------
1 | 205 | 19 | 4 | 3
2 | 205 | 20 | 5 | 4
3 | 205 | 21 | 4 | 5
Note: There are two people involved in providing the score. One is supervisee and another is supervisor.
The score provided by the supervisee is kept in the column named self_score. In the table, employee_id is the id of the supervisee. Supervisor also gives the rating to the supervisee for the same question as shown aboove in the table.
I have generated the data from the database as an Array which is shown below:
$params = Array
(
[selfscore_19] => 4
[supervisorscore_19] => 3
[selfscore_20] => 5
[supervisorscore_20] => 4
[selfscore_21] => 4
[supervisorscore_21] => 5
)
Note: In the key named [selfscore_19] , selfscore_ is the string and 19 is the question id.
Questions are same for both - 'self' and 'supervisor'.
So I have appended the strings named 'selfscore' and 'supervisorscore' with the question_id.
In the array shown below, key is: [selfscore_19] which has been appended with the question_id i.e 19 and
the value is score provided by 'self' which is 4.
And other data follows similar pattern.
Attempt:
The code below shows the attempt done by me so far:
Note: I have only shown the main part of the method.
foreach($params as $key => $value){
$exp_key = explode('_', $key);
if($exp_key[0]=='selfscore'){
$arr_result[] = $value;
}
}
foreach($params as $key => $value){
$exp_key = explode('_', $key);
if($exp_key[0]=='supervisorscore'){
$arr_result[] = $value;
}
}
if(isset($arr_result)){
echo '<pre>';
print_r($arr_result);
echo '<pre>';
}
This is the output of the above code:
Current Output:
Array
(
[0] => 4
[1] => 5
[2] => 4
[3] => 3
[4] => 4
[5] => 5
)
Now I want to tranform the Current Output in the form of following Output.
Although I have already researched about this case, but I am finding it a bit tricky.
What modification should I do to achieve the required output?
Suggestions are highly appreciated.
Required Output:
$score['self_score']=array(
array('question_id'=>19,'score'=>4)
array('question_id'=>20,'score'=>5)
array('question_id'=>21,'score'=>4)
);
$score['supervisor_score']=array(
array('question_id'=>19,'score'=>3),
array('question_id'=>20,'score'=>4)
array('question_id'=>21,'score'=>5)
);
Do it with a single loop. Use the first part of $exp_key as the key of the resulting array, and the second part as the value of the question_id key of the sub-array.
foreach ($arr_result as $key => $value) {
$exp_key = explode("_", $key);
$score[$exp_key[0]][] = array("question_id" => $exp_key[1], "score" => $value);
}
I think I'll recommend that you use a UNION to join two simple queries so that your initial resultset is very close to what you want (close enough to simply iterate and/or modify it).
SQL: (Demo)
(SELECT 'group' AS 'self_score', question_id, self_score
FROM rating
WHERE employee_id = 205
ORDER BY id)
UNION
(SELECT 'supervisor_score', question_id, supervisor_score
FROM rating
WHERE employee_id = 205
ORDER BY id)
Resultset:
group | question_id | self_score
------------------|---------------|------------
self_score | 19 | 4
self_score | 20 | 4
self_score | 21 | 5
supervisor_score | 19 | 3
supervisor_score | 20 | 4
supervisor_score | 21 | 5
If you are open to a PDO solution, fetchAll(PDO::FETCH_GROUP) will come in pretty handy.

Parse through a nested array and save it in mysql db with parent id

I have a nested array like the following:-
array(
array(
'id' => 45cfeteuid536hjj929,
'name' = 'Cuisines',
'children' => array(
array(
'id' => 45gcfeteuid536hjj929,
'name' = 'Itlaian',
),
array(
'id' => 45bjfe78ng5d536hjj92,
'name' = 'Indian',
'children' => array(
array(
'id' => 457hfe78ng5d53ghy56j,
'name' = 'Punjabi'
)
)
)
)
)
);
I have a table like this:-
|--------------------------------|
| id | name | parent_id |
|--------------------------------|
I want data to be inserted like this:-
|---------------------------------------------------------------|
| id | name | parent_id | api_id |
|---------------------------------------------------------------|
| 1 | Cuisines | 0 | 45cfeteuid536hjj929 |
|---------------------------------------------------------------|
| 2 | Italian | 1 | 45gcfeteuid536hjj929 |
|---------------------------------------------------------------|
| 3 | Indian | 1 | 45bjfe78ng5d536hjj92 |
|---------------------------------------------------------------|
| 4 | Punjabi | 3 | 457hfe78ng5d53ghy56j |
|---------------------------------------------------------------|
The parent_id of the child is the id of the object to which it belongs. The id of the table are autoincrement value generated automatically by the mysql db.
For example:-
Step 1: While saving Cuisine, the id (autoincrement in nature) saved
is 1. Since it is the root, hence parent_id = 0.
Step 2: While saving Italian, the id (autoincrement in nature)
saved is 1. Since it is a child of Cuisines, the parent_id = 1
How can I save the nested array in such way?
One way would be to generate insert statements that look like this (assuming your table is called tab):
insert into tab(name, parent_id, app_id)
select 'Cuisines', coalesce(min(id), 0), '45cfeteuid536hjj929' from tab
where app_id = '';
insert into tab(name, parent_id, app_id)
select 'Itlaian', coalesce(min(id), 0), '45gcfeteuid536hjj929' from tab
where app_id = '45cfeteuid536hjj929';
insert into tab(name, parent_id, app_id)
select 'Indian', coalesce(min(id), 0), '45bjfe78ng5d536hjj92' from tab
where app_id = '45cfeteuid536hjj929';
insert into tab(name, parent_id, app_id)
select 'Punjabi', coalesce(min(id), 0), '457hfe78ng5d53ghy56j' from tab
where app_id = '45bjfe78ng5d536hjj92';
These queries will find the parent ID via the app_id that parent should have. No value for the id column is inserted, as it is assumed that the database will generate it upon insertion.
Here is a recursive PHP function which generates those statements. You'll have to adapt it to actually execute those statements with whatever API you use (PDO, mysqli, ...):
function insertRecords($data, $parent = "") {
foreach($data as $row) {
// Replace next echo statement with the code to actually execute this SQL:
echo "insert into tab(name, parent_id, app_id) select '$row[name]', coalesce(min(id), 0), '$row[id]' from tab where app_id = '$parent';\n";
if (isset($row["children"])) insertRecords($row["children"], $row["id"]);
}
}
Assuming your nested data structure is stored in variable $data, call the above function like this:
insertRecords($data);

Get the data which in two dimensional array

Hello This may looks to be simple task but I am getting struck... In my application i am getting an array which would be like
Array
(
[0] => Array
(
[home_id] => 1
[distance] => 12
)
[1] => Array
(
[home_id] => 3
[distance] => 14
)
[2] => Array
(
[home_id] => 94
[distance] => 1.679713069
)
.
.
.
.
)
And my table looks like
home_id | home_name
1 | My home 1
2 | My home 2
3 | My home 3
From this array i will get the home_id which is in database table. So How can i get the result details which includes the home_name and the distance from the first array which might be like
home_name | distance
___________________________
My home 1 | 0.562620830044
My home 3 | 14
Thank you in advance
Loop through your array and get the home_name from database using codeigniter active record query -
foreach($yourArray as $row)
{
$id = $row['home_id'];
$distance = $row['distance'];
$db_result = $this->db->get_where('yourtable', array('home_id' => $id));
if($db_result && $db_result->num_rows() > 0){
$result = $db_result->row();
$home_name = $result->home_name;
}
}
If you cannot JOIN the two tables in one query and have to use that array then you can do:
foreach($yourArray as $home)
{
$id=$home["home_id"];
$distance=$home["distance"];
$id=intval($id);
$sql="SELECT home_name FROM yourTable WHERE home_id=$id"; // execute this query to get name
}
From this array i will get the home_id which is in database table. So How can i get the result details which includes the home_name and the distance from the first array which might be like
If you want to get home details from table home_details_table using the id you get from the main array, so replace the field home_namein home_details_table by home_id and link both tables as a One to Many relation.
home_table:
home_id | home_name
1 | My home 1
2 | My home 2
3 | My home 3
home_detail_table:
home_id | distance
1 | 0.562620830044
3 | 14
Then with a JOIN, you will be able to do :
foreach($mainArray as $home)
{
$id = $home["home_id"];
$sql="SELECT h.home_id, h.home_name, d.home_distance FROM home_table h JOIN home_details_table d ON h.home_id = d.home_id WHERE h.home_id = ".$id;
// with this query you will have the name and distance of the given home id.
}

Trying to group up results of a SQL multi table query

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'

Get data from two mysql tables, where row of one table is connected to many in other

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 />";
}

Categories