get nested json response - php

I have table store_profile like this
id Storename Storetype address
1 Samsung Store Electronics Delhi
2 Levi Clothing Mumbai
3 Soni Electronics Bangalore
and second table Offers
id Store_id offer price
1 Samsung Store flat 30% off 20000
2 Levi Exchange 5000
3 Samsung Store Exchange offer 40000
I want to get all the store details from store_profile for particular type,say Electronics and for each store their offers in single row,not repeated as I am getting from this syntax in json mysql query is :-
SELECT * , Offers.Store_id
FROM Store_profile INNER JOIN
Offers
ON Store_profile.Storename = Offers.Store_id AND
Store_profile.Storetype like '%Electronics%'
Here is my php code
$sql ="SELECT * , Offers.Store_id FROM Store_profile INNER JOIN Offers ON Store_profile.Storename = Offers.Store_id AND Store_profile.Storetype like '%Electronics%' LIMIT 0 , 300 ";
$r = mysqli_query($con,$sql);
$result = array();
while($row = mysqli_fetch_array($r)){
array_push($result,array(
'Store_Name'=>$row['Storename'],
'Store_address'=>$row['address'],
'Offer_Title'=>$row['offer'],
'MRP_Price'=>$row['price'],
)
);
}
echo json_encode(array('result'=>$result));
mysqli_close($con);

... i want to get json like this result["Storename"-Samsung Store,Store_address - Delhi,Offer[Offer_Title-Flat 30% Off,MRP_Price20000,Offer_Title-Exchange offer,MRP_Price40000 ]]
Change your while() loop and the subsequent json_encode() function call in the following way,
$result = array();
while($row = mysqli_fetch_array($r)){
if(!isset($result[$row['Store_id']])){
$result[$row['Store_id']] = array('Store_Name'=>$row['Storename'], 'Store_address'=>$row['address']);
}
$result[$row['Store_id']]['offer'][] = array('Offer_Title'=>$row['offer'],'MRP_Price'=>$row['price']);
}
echo json_encode(array('result' => array_values($result)));
Update:
From your comment,
... i have one store in store_profile but this store doesnt have any offer in Offers table. I am not getting this store's data in my json
You have to use LEFT JOIN to include all the matched rows from the Store_profile table in the result set. Furthermore, you need to use WHERE instead of AND after the joining condition. So your query should be like this:
SELECT * , Offers.Store_id
FROM Store_profile
LEFT JOIN Offers
ON Store_profile.Storename = Offers.Store_id
WHERE Store_profile.Storetype LIKE '%Electronics%'
LIMIT 0 , 300
Subsequently, change your while() loop and json_encode() function call in the following way,
$result = array();
while($row = mysqli_fetch_array($r)){
if(!isset($result[$row['Storename']])){
$result[$row['Storename']] = array('Store_Name'=>$row['Storename'], 'Store_address'=>$row['address']);
}
if(isset($row['offer']) && isset($row['price'])){
$result[$row['Storename']]['offer'][] = array('Offer_Title'=>$row['offer'],'MRP_Price'=>$row['price']);
}else{
$result[$row['Storename']]['offer'] = array();
}
}
echo json_encode(array('result' => array_values($result)));

Related

Select from 2 tables not working with php mysql

I have two different tables of the following structure:
grouprel
id | userId | pupID | groupId
pupils
id | userId | fname | lname
pupId in groulrel is equal to id in pupils.
I want to fetch pupils from a different group and then order them by fname, lname.
Now I have two queries like this:
$q = "SELECT * FROM grouprel WHERE userid = ". $userid ." AND groupId = ". $_GET['id'] ."";
$r = mysqli_query($mysqli, $q);
while ($rows = mysqli_fetch_object($r)) {
$query = "SELECT id, fname, lname FROM pupils WHERE userid = ". $userid ." AND id = ". $rows->pupId ." AND status = 0 ORDER BY fname, lname";
$result = mysqli_query($mysqli, $query);
while($row = mysqli_fetch_object($result)) {
echo stuff...
}
}
This works, but it doesn't order the names alphabetically like I want to.
How could I fix this?
This is iterating over the first query:
while ($rows = mysqli_fetch_object($r)) {
And this iterates over each instance of the second query:
while($row = mysqli_fetch_object($result)) {
So if the first query returns 1,2,3, and each iteration of the second query returns A,B, then your output would be:
1 A
1 B
2 A
2 B
3 A
3 B
The second query is ordering by the ORDER BY clause you gave it. But you are ordering the entire output by the first query.
Ultimately, why do you need these separate queries at all? Executing a database query in a loop is almost always the wrong idea. It looks like all you need is one query with a simple JOIN. Guessing on your logic, something like this:
SELECT
pupils.id, pupils.fname, pupils.lname
FROM
pupils
INNER JOIN grouprel ON pupils.id = grouprel.pupId
WHERE
pupils.userid = ?
AND grouprel.groupId = ?
AND pupils.status = 0
ORDER BY
fname, lname
It may take a little tweaking to match exactly what you're looking for, but you can achieve your goal with a single query instead of multiple separate queries. Then the results of that query will be ordered the way you told MySQL to order them, instead of the way you told PHP to order them.

Joining two mysql tables and populate an array in php

I have two tables
First table name is "Library"
ID Name
1 A
2 B
Second table name is "Books"
BID Book_Creater Book_Name
1 Variation1 Book1
1 Variation2 Book2
1 Variation3 Book3
2 Variation1 Book4
2 Variation2 Book5
The sql is
$sql = mysql_query("select library.ID,books.Book_Creater,books.Book_name from library,books where library.ID = books.BID;
Result is
ID Book_Creater Book_name
1 Variation1 Book1
1 Variation2 Book2
1 Variation3 Book3
2 Variation1 Book4
2 Variation2 Book5
Now I would like to create an array which should look like and this is where I am stuck.
array(
[1] => array(
[Variation1] => Book1
[Variation2] => Book2
[Variation3] => Book3
)
[2] => array(
[Variation1] => Book4
[Variation2] => Book5
)
)
Any suggestion will do great.
$res = array();
//for each result row
while($row = mysql_fetch_array($sql))
{
//add a row to the multi dimensional result array
//where the first key = id and the second key = Book_Creater
$res[$row['id']][$row['Book_Creater']] = $row['Book_name'];
}
print_r($res);
Simple way is to do a join as you currently do, and push them into an array as you loop around (possibly for neatness creating a new sub array explicitly when the ID as a key doesn't already exist).
Something like this:-
<?php
$store_array = array();
$sql = mysql_query("SELECT library.ID,books.Book_Creater,books.Book_name
FROM library
INNER JOIN books
ON library.ID = books.BID");
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
if (!array_key_exists($row['ID'], $store_array))
{
$store_array[$row['ID']] = array();
}
$store_array[$row['ID']][$row['Book_Creater']] = $row['Book_name']
}
print_r($store_array);
?>
You could also shuffle some effort onto the database and bring things back concatenated together. Then just split the results to put into the array:-
<?php
$store_array = array();
$sql = mysql_query("SELECT library.ID, GROUP_CONCAT(CONCAT_WS('#~#', books.Book_Creater,books.Book_name)) AS details
FROM library
INNER JOIN books
ON library.ID = books.BID
GROUP BY library.ID");
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$store_array[$row['ID']] = array();
$details = explode(',', $row['details']);
foreach($details as $detail)
{
$detail_line = explode('#~#', $row['detail']);
$store_array[$row['ID']][$detail_line[0]] = $detail_line[1];
}
}
print_r($store_array);
?>
Note that if you are doing this with real data you probably want to chose delimiters which are not going to appear in your data, and also that by default GROUP_CONCAT has a fairly limited max length.
Note also I have used mysql_* functions as that is what you seem to be using, but these are deprecated and probably shouldn't be used now.

Join ID & Name from Two Separate Tables

I have two tables...
Table 1 (keywordsTbl)
KeyID Key_Name
================================
1 Biology
2 Entertainment
Table 2 (profileTbl)
Keyword_ID Key_Name
================================
1(from keywordsTbl) Biology(from keywordsTbl)
2(from keywordsTbl) Entertainment(from keywordsTbl)
My query in profileTbl is indexing KeyID from the keywordsTbl and its working fine. The only problem is my output shows up like so (no array). :
Seems like its indexing only the 1st keyID... The results only show 1 single keyword even though there are more than one keyID being placed in the row:
My query looks as so:
include 'db.php';
$sql = mysqli_query($con,"SELECT * FROM profileTable, addKeywordTable ORDER BY LaName ASC");
while ($row = mysqli_fetch_array($sql))
{
$fname = $row['FirName'];
$lname = $row['LaName'];
$title = $row['Title'];
$keys = $row['Keyword_Name'];
$id = $row['source_ID'];
if(!in_array($title,array('',null)) && !empty($title)):
$title = '('.$title.')';
else:
$title = '';
endif;
What's the easiest way to show an array when two tables are being used? Would a join work better in this case?
I am not 100% sure that this is what you are asking, but if you want a list of results based on a join for KeyID you can do something like this:
SELECT p.Laname, p.FiName, GROUP_CONCAT(k.Key_Name)
FROM ProfileTable AS p
JOIN addKeywordTable AS k ON k.KeyID = p.Keyword_ID
GROUP BY p.LaName, p.FiName
If you want to include more files in the select list you need to add them to the GROUP BY list or use an aggregate function (GROUP_CONCAT, MAX, MIN, etc) on them in the select list.

MySQL/PHP query to reverse relationship

I have a mysql table with the following columns:
ID Units
1 1234,6543,9876
2 1234,6543
3 6543
4 9876
5 0987
I would like to reverse the relationship to get an output like this:
Unit IDs
1234 1,2
6543 1,2,3
9876 1,4
0987 5
I was wondering if this could be done in a query or some php, without chunking through with explodes etc?
Using comma-separated lists in SQL is awkward. This is a denormalized design, and SQL is not well suited to work with data in this format.
I would fetch all the data back into PHP and manipulate it there.
$id_per_unit = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$unit_array = explode(",", $row["Units"]);
foreach ($unit_array as $unit) {
$id_per_unit[$unit][] = $row["Id"];
}
}
Something like this:
$query = "SELECT `Unit`, `IDs` FROM `table` ORDER BY `Unit`";
$data = mysqli_query($con, $query);
$prev_unit = '';
while ($row = mysqli_fetch_array($data)) {
if ($prev_unit != $row['Unit']) {
// echo a new row with the new unit and then ID
} else {
// echo just the ID in the same row, this unit is the same as the last one.
}
$prev_unit = $row['Unit'];
}
With only SQL, you can do something like this :
SELECT unit , GROUP_CONCAT(id)
FROM (
SELECT id,substring_index(Units,',',1) AS unit
FROM Table1
UNION
SELECT id,REPLACE(
REPLACE(SUBSTRING_INDEX(Units,',',2),SUBSTRING_INDEX(Units,',',1),'')
,',','') AS unit
FROM Table1
UNION
SELECT id,REPLACE(
REPLACE(SUBSTRING_INDEX(Units,',',3),SUBSTRING_INDEX(Units,',',2),'')
,',','') AS unit
FROM Table1) AS UNITS
WHERE unit != ''
GROUP BY unit
See SQLFIDDLE

search for element in a php array

I've got
a users table named "members"
a rooms table named "rooms"
a table that associates the user id to the ids of the rooms "membersRooms"
I should write a loop that prints a dropdown for each user with all the rooms, but that adds the attribute "selected" to rooms associated with the user
What's wrong with this loop?
$members = mysql_query("SELECT * FROM members ");
$rooms = mysql_query("SELECT * FROM rooms");
while($member = mysql_fetch_array($members)){
echo("<select>");
$roomsOfUser = mysql_query("SELECT roomID FROM membersRooms WHERE userID=".$member["id"]);
$cuArray = mysql_fetch_array($roomsOfUser);
while($room = mysql_fetch_array($rooms)){
if(in_array($room["id"],$cuArray,true))
echo("<option selected='selected'>".$room["roomName"]."</option>");
else
echo("<option>".$class["roomName"]."</option>");
}
echo("</select>");
}
To make this a little easier on you, you could try utilizing left and right joins on your database. This would significantly reduce your server load and still allow you to do the same functionality.
I believe, if I'm reading your database structure right, that you'ld want something along the lines of:
SELECT members.id as memberID, rooms.id as roomID, rooms.roomName, membersRooms.roomID as memberRoom
FROM members
LEFT JOIN membersRooms
ON members.id = membersRooms.userID
RIGHT JOIN rooms
ON membersRooms.roomID = rooms.id
Then in PHP you should be able to just keep track of when your memberID changes, and when it does, start a new select. If I didn't totally bungle that SQL (which I might have) then the resulting rows should look something like:
memberID | roomID | roomName | memberRoom
1 1 foo 1
1 2 bar 1
2 1 foo 1
2 2 bar 1
So on your loop iteration you would use roomID and roomName to build your select, and if RoomID matched memberRoom then you would select that row.
$rooms query while is dead
while runs once time in while
put this $rooms = mysql_query("SELECT * FROM rooms"); query line
in first while
OK, so you need information from 3 tables - members, rooms, and membersRooms. The rows from members and membersRooms line up 1:1, so we can get both of those with 1 query.
This method will minimize the number of queries needed - if you ever see yourself querying the database in a loop, ask yourself if there's a better way.
$member_query = mysql_query("SELECT * FROM members LEFT JOIN membersRooms ON (members.id = membersRooms.userID)");
$room_query = mysql_query("SELECT * FROM rooms");
$rooms = array();
while ($room = mysql_fetch_assoc($room_query))
$rooms[] = $room;
while ($member = mysql_fetch_assoc($member_query)) {
echo '<select>';
foreach($rooms as $room) {
echo "<option value='{$room['roomID']}' ";
if ($member['roomID'] == $room['id'])
echo 'selected="selected"';
echo ">{$room['roomName']}</option>";
}
echo '</select>';
}
It's worth noting that if members:rooms is a 1:many relation, you don't need to use a third table to join them - just add a roomId to members, and you're fine.

Categories