Basic question!
I have 2 tables
PRODUCE
+-----+--------------+
| id | fruit_name |
+--------------------+
| 1 | Apple |
| 2 | Banana |
| 3 | Carrot |
+-----+--------------+
VARIETIES
+-----+---------------+----------------+
| id | fk_fruit_id | variety_name |
+-----+---------------+----------------+
| 1 | 1 | Cox |
| 2 | 1 | Braeburn |
| 3 | 2 | Chester |
| 4 | 3 | Kotaka |
| 5 | 3 | Imperial |
| 6 | 3 | Oneal |
+-----+---------------+----------------+
I'd like to output a list of varieties per fruit e.g.
APPLE - Cox, Braeburn
BANANA - Chester
CARROT - Kotaka, Imperial, Oneal
My current code is
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
$result = mysql_query($query) or die('Error : ' . mysql_error());
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$produce_fruit_code = $row['fruit_code'];
$variety_name = $row['variety_name'];
echo $produce_fruit_code.' - '.$variety_name.'<br/>';
}
which outputs:
Apple - Cox
Apple - Braeburn
Banana - Chester
Carrot - Kotaka
Carrot - Imperial
Carrot - Oneal
Not a million miles away, but still not there. Any help is much appreciated, thanks!
You probably could get one chunky sql statement to do that for you but I'd opt for data juggling with arrays.
For example (not tested and excuse the formatting):
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
$result = mysql_query($query) or die('Error : ' . mysql_error());
$res=array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$produce_fruit_code = $row['fruit_code'];
$variety_name = $row['variety_name'];
if(isset($res[$produce_fruit_code])){
$res[$produce_fruit_code]+=','.$variety_name;
}else{
$res[$produce_fruit_code]=$variety_name;
}
}
print_r($res);
If you are using MySQL you can use the group_concat extension on grouping. Something along the lines of:
SELECT
f.fruitname as fruit,
GROUP_CONCAT(distinct v.varietyname separator ',') as variety
FROM fruit f JOIN varieties v ON produce.id = varieties.fk_fruit_id;
or similar. Sorry my sql is a little rusty quite now.
For more look at this article
http://www.mysqlperformanceblog.com/2006/09/04/group_concat-useful-group-by-extension/
and of course here:
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
If you dont work with MySQL and your database doesn't support group_concat think about buffering those results. In large databases and with many simultaneous users your application can considerably slow down when having to download all data and store it in locally every time.
This won't get you all the way, but it will get you most of what you want. There are some edge cases that are problematic.
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
$result = mysql_query($query) or die('Error : ' . mysql_error());
$produce_fruit_code = "";
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
if ($produce_fruit_code != $row['fruit_code'])
{
$produce_fruit_code = $row['fruit_code'];
echo "<br/>".$produce_fruit_code." - ". $row['variety_name'];
} else {
echo ", ".$row['variety_name'];
}
}
$query = "SELECT * FROM produce, varieties WHERE produce.id = varieties.fk_fruit_id";
echo "<dl>";
$result = mysql_query($query) or die('Error : ' . mysql_error());
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
if($row['fruit_name'] != $current_fruit_name) {
$current_fruit_name = $row['fruit_name'];
echo "<dt>$current_fruit_name</dt>";
}
echo "<dd>" . $row['variety_name'] . "</dd>";
}
echo "";
If you want some CSS that will make a definition list look like the Name - X,Y,Z like in the question, let me know.
You can query this directly
SELECT
f.fruitname as fruit,
GROUP_CONCAT(distinct v.varietyname separator ',') as variety
FROM fruit f JOIN varieties v ON produce.id = varieties.fk_fruit_id;
GROUP BY produce.id
Sort everything into arrays in your while loop. This should work:
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$produce_fruit_code = $row['fruit_code'];
$variety_name = $row['variety_name'];
if ($produce_fruit_code == "Apple") {
$apple_array[] = $variety_name;
}
if ($produce_fruit_code == "Banana") {
$banana_array[] = $variety_name;
}
if ($produce_fruit_code == "Carrot") {
$carrot_array[] = $variety_name;
}
}
echo "Apples:" . implode(", ", $apple_array) . "<br/>";
echo "Bananas:" . implode(", ", $bananas_array) . "<br/>";
echo "Carrots:" . implode(", ", $carrots_array) . "<br/>";
Related
I want to display the comment only once e.g (testsetest) with the related images (which has the same imagesid by connecting the two tables).
Example (that I want to achieve):
comment: fool with images: name1, name 2
Caption of the wrong output.
The database structure
posts:
| commentid | comment | iamgesid |
------------------------------------
| 1 | fool | 5557 |
| 2 | fool2 | 5585 |
------------------------------------
multiple_image:
| id | image | imagesid |
---------------------------
| 1 | name1 | 5557 |
| 2 | name2 | 5557 |
| 3 | name3 | 5585 |
---------------------------
This is my current code:
$sql = "SELECT image, posts.imagesid, multiple_image.imagesid, comment
FROM multiple_image JOIN posts ON (multiple_image.imagesid=posts.imagesid)";
$result = $conn->query($sql);
if (!$result) {
trigger_error('Invalid query: ' . $conn->error);
}
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo $row['comment'];
$imgs= "<div id='img_div'><img width='' src='upload/".$row['image']."' ></div>";
echo $imgs;
}
}
You will need to control break the result and order by the commentid
Please see the updated code.
$sql = "SELECT
image,
posts.imagesid,
multiple_image.imagesid,
comment
FROM
multiple_image
JOIN posts ON (multiple_image.imagesid=posts.imagesid)
ORDER BY
commentid
";
$result = $conn->query($sql);
if (!$result) {
trigger_error('Invalid query: ' . $conn->error);
}
if ($result->num_rows > 0) {
// output data of each row
$comment = '';
while($row = $result->fetch_assoc()) {
if($comment != $row['comment']){
echo $row['comment'];
$comment = $row['comment'];
}
$imgs= "<div id='img_div'><img width='' src='upload/".$row['image']."' ></div>";
echo $imgs;
}
}
You can create a flag and check if it is 0. If it is 0 then you can show comment else you dont need to show comment. Check below code:
if ($result->num_rows > 0) {
// output data of each row
$loop = 0;
while ($row = $result->fetch_assoc()) {
if ($loop == 0) {
echo $row['comment'];
}
$imgs = "<div id='img_div'><img width='' src='upload/" . $row['image'] . "' ></div>";
echo $imgs;
$loop++;
}
}
Hope it helps you.
I hope it will help out:
$sql = "SELECT
image,
posts.imagesid,
multiple_image.imagesid,
comment
FROM
multiple_image
JOIN posts ON (multiple_image.imagesid=posts.imagesid)
ORDER BY
commentid";
$result = $conn->query($sql);
if (!$result) {
trigger_error('Invalid query: ' . $conn->error);
}
if ($result->num_rows > 0) {
$comment = array();
while ($row = $result->fetch_assoc()) {
// check imagesid is not exist in array
if (in_array($row['imagesid'], $comment) == false) {
echo $row['comment'];
$comment[] = $row['imagesid'];
}
$imgs = "<div id='img_div'><img width='' src='upload/" . $row['image'] . "' ></div>";
echo $imgs;
}
}
I am working on Codeigniter and i have following tables, i want that first one subject name to be printed then all its sub-subjects and so on as given below :
Subjects:
-----------------------
id | Subjects Name
-----------------------
1 | Mathematics
2 | Physics
3 | Chemistry
Subsections:
---------------------------------------------
id | subject_id | SubsectionsName
---------------------------------------------
1 2 Electromagnetism
2 1 Algebra
3 3 Organic Chemistry
4 1 Geometry and Topology
5 2 Mechanics
I want following output
Mathematics
Algebra
Geometry and Topology
Physics
Electromagnetism
Mechanics
Chemistry
Organic Chemistry
for that i am using following code but it is not giving me correct output.
$condition = "id =" . "'" . $subject_id . "'";
$this->db->select('*');
$this->db->from('subject');
$this->db->where($condition);
$query = $this->db->get();
if ($query->num_rows() > 0) {
foreach($query->result_array() as $row)
{
$rows[] = $row;
$condition = "subject_id =" . "'" . $row['id'] . "'";
$this->db->select('*');
$this->db->from('subsections');
$this->db->where($condition);
$query_course_material = $this->db->get();
foreach($query->result_array() as $row1)
{
$rows[] = $row1;
}
}
return $rows;
} else {
return false;
}
Inner foreach is having incorrect variable. It should have $query_course_material instead of $query. Please check below :
$query_course_material = $this->db->get();
foreach($query_course_material->result_array() as $row1)
{
$rows[] = $row1;
}
I need help with DISTINCT. I would like to display Distinct row but display also all rows
Example this table from database:
+----+-----+-----+
|col1|col2 |col3 |
+----+-----+-----+
|A |one |two |
|A |three|four |
|A |five |six |
|B |seven|eight|
|B |nine |ten |
+----+-----+-----+
I would like the display to look like this :
A
one |two
three|four
five |six
B
seven|eight
nine |ten
Can anyone help?
The easiest way would be to fetch all rows from the database, and then group them in PHP.
// Querying:
$query = mysql_query('select * from tbl');
$results = array(); // Store all results in an array, grouped by col1
while($row = mysql_fetch_assoc($query)) {
$col1 = $row['col1'];
// This is basically grouping your rows by col1
if(!isset($results[$col1]))
$results[$col1] = array();
$results[$col1][] = $row;
}
// Displaying:
foreach($results as $col1 => $rows) {
echo "<h1>" . $col1 . "</h1>";
foreach($rows as $row) {
echo $row['col2'] . "|" . $row['col3'] . "<br />";
}
}
Yields:
<h1>A</h1>
one |two
three|four
five |six
<h1>B</h1>
seven|eight
nine |ten
Note that I use the deprecated mysql_functions just for simplicity, do not use them in production.
Here is how you can do it
$query="select
distinct (col1) as col1,
GROUP_CONCAT(col2) as col2,
GROUP_CONCAT(col3) as col3
FROM test
group by col1";
$query = mysql_query($query);
This will fetch this output
col1 col2 col3
A one,three,five two,four,six
B seven,nine eight,ten
while($row = mysql_fetch_assoc($query))
{
$col1 = $row['col1'];
$col2 = explode(',',$row['col2']);
$col3 = explode(',',$row['col3']);
for($i=0;$i<=count($col2);$i++)
{
$value = '';
if(isset($col2[$i])){
$value = $col2[$i];
$value .= ' | ';
}
if(isset($col3[$i])){
$value .= $col3[$i];
}
echo $value;
}
}
i have a table General whose structure like this
----------------------------------
id | name | parent_id
------------------------------------
1 | root_category | Null
2 | Appare | 1
3 | Accessories | 1
4 | Shirt | 2
5 | Pants | 2
6 | hand Bags | 3
7 | jewelry | 3
And i store the value of general table using from in my product table
product table which contain all the information about product
in product table
p_id | 1
p_name | bla
p_weight | 250
g_id | 5
g_name | pants
g_parent | 2
i Want to generate complete tree using
->g_id -> g_name -> g_parent
tree should look like this
Root Category
- Apparel
-- Shirts
-- Pants
- Accessories
-- Handbags
-- Jewelry
i have tried recursive function but its not working which is
function get_categories($parent = $g_parent)
{
$html = '<ul>';
$query = mysql_query("SELECT * FROM `general` WHERE `parent_id` = '$parent'");
while($row = mysql_fetch_assoc($query))
{
$current_id = $row['id'];
$html .= '<li>' . $row['name'];
$has_sub = NULL;
$has_sub = mysql_num_rows(mysql_query("SELECT COUNT(`parent_id`) FROM `general` WHERE `parent_id` = '$current_id'"));
if($has_sub)
{
$html .= get_categories($current_id);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
print get_categories();
but its not working.... :(
You should try this... its working code.. also see the output screenshot (output screen)
<?php
function get_categories(){
$con = mysql_connect("localhost","root","");
if (!$con){
die('Could not connect: ' . mysql_error());
}
mysql_select_db("stackoverflow", $con);
$result = mysql_query("SELECT g.`name` AS `category`, GROUP_CONCAT(gj.`name`) AS `name`
FROM `general` g INNER JOIN `general` gj ON g.`id` = gj.`parent_id` GROUP BY g.`id` ");
$i=0;
while($row = mysql_fetch_array($result)){
$data[$i]['category'] = $row['category'];
$data[$i]['name'] = $row['name'];
$i++;
}
$html = $data[0]['category']."<br>";
unset($data[0]);
foreach($data as $key => $listing){
$html .= " - ".$listing['category']."<br>";
$exp = explode(",",$listing['name']);
$count_exp = count($exp);
for($j=0; $j<=$count_exp-1;$j++){
$html .= " -- ".$exp[$j]."<br>";
}
}
return $html;
}
print_r(get_categories());
?>
Output Screen
Change this
print get_categories();
To
print get_categories(1);
an empty string is not going to match a NULL value in MySQL, hence you need to supply your starting id. Unless you wanna modify your function to do the extra checking if $parent is null.
try this with some changing :
function get_categories($parent)
{
$html = '<ul>';
$query = mysql_query("SELECT * FROM `general` WHERE `parent_id` = '$parent'");
while($row = mysql_fetch_assoc($query))
{
$current_id = $row['id'];
$html .= '<li>' . $row['name'];
$has_sub = NULL;
$has_sub = mysql_num_rows(mysql_query("SELECT COUNT(`parent_id`) as count FROM `general` WHERE `parent_id` = '$current_id'")); // change here
if($has_sub['count'] > 0) // change here
{
$html .= get_categories($current_id);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
print get_categories(1); // change here
I'm building a form with php/mysql. I've got a table with a list of locations and sublocations. Each sublocation has a parent location. A column "parentid" references another locationid in the same table. I now want to load these values into a dropdown in the following manner:
--Location 1
----Sublocation 1
----Sublocation 2
----Sublocation 3
--Location 2
----Sublocation 4
----Sublocation 5
etc. etc.
Did anyone get an elegant solution for doing this?
NOTE: This is only psuedo-code.. I didn't try running it, though you should be able to adjust the concepts to what you need.
$parentsql = "SELECT parentid, parentname FROM table";
$result = mysql_query($parentsql);
print "<select>";
while($row = mysql_fetch_assoc($result)){
$childsql = "SELECT childID, childName from table where parentid=".$row["parentID"];
$result2 = mysql_query($childsql);
print "<optgroup label=\".$row["parentname"]."\">";
while($row2 = mysql_fetch_assoc($result)){
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>";
}
print "</select>";
With BaileyP's valid criticism in mind, here's how to do it WITHOUT the overhead of calling multiple queries in every loop:
$sql = "SELECT childId, childName, parentId, parentName FROM child LEFT JOIN parent ON child.parentId = parent.parentId ORDER BY parentID, childName";
$result = mysql_query($sql);
$currentParent = "";
print "<select>";
while($row = mysql_fetch_assoc($result)){
if($currentParent != $row["parentID"]){
if($currentParent != ""){
print "</optgroup>";
}
print "<optgroup label=\".$row["parentName"]."\">";
$currentParent = $row["parentName"];
}
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>"
print "</select>";
Are you looking for something like the OPTGROUP tag?
optgroup is definitely the way to go. It's actually what it's for,
For example usage, view source of http://www.grandhall.eu/tips/submit/ - the selector under "Grandhall Grill Used".
You can use and space/dash indentation in the actual HTML. You'll need a recusrive loop to build it though. Something like:
<?php
$data = array(
'Location 1' => array(
'Sublocation1',
'Sublocation2',
'Sublocation3' => array(
'SubSublocation1',
),
'Location2'
);
$output = '<select name="location">' . PHP_EOL;
function build_items($input, $output)
{
if(is_array($input))
{
$output .= '<optgroup>' . $key . '</optgroup>' . PHP_EOL;
foreach($input as $key => $value)
{
$output = build_items($value, $output);
}
}
else
{
$output .= '<option>' . $value . '</option>' . PHP_EOL;
}
return $output;
}
$output = build_items($data, $output);
$output .= '</select>' . PHP_EOL;
?>
Or something similar ;)
Ideally, you'd select all this data in the proper order right out of the database, then just loop over that for output. Here's my take on what you're asking for
<?php
/*
Assuming data that looks like this
locations
+----+-----------+-------+
| id | parent_id | descr |
+----+-----------+-------+
| 1 | null | Foo |
| 2 | null | Bar |
| 3 | 1 | Doe |
| 4 | 2 | Rae |
| 5 | 1 | Mi |
| 6 | 2 | Fa |
+----+-----------+-------+
*/
$result = mysql_query( "SELECT id, parent_id, descr FROM locations order by coalesce(id, parent_id), descr" );
echo "<select>";
while ( $row = mysql_fetch_object( $result ) )
{
$optionName = htmlspecialchars( ( is_null( $row->parent_id ) ) ? "--{$row->descr}" : "----{$row->desc}r", ENT_COMPAT, 'UTF-8' );
echo "<option value=\"{$row->id}\">$optionName</option>";
}
echo "</select>";
If you don't like the use of the coalesce() function, you can add a "display_order" column to this table that you can manually set, and then use for the ORDER BY.