views:

106

answers:

3

Hello, I have a simple question but I don't know which term I should use to find the answer (english is not my first language).

I have a classical database design of products like and categories.

CREATE TABLE IF NOT EXISTS `a` (
  `id_a` int(11) NOT NULL auto_increment,
  `type` varchar(255) NOT NULL,
  PRIMARY KEY  (`id_a`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;

CREATE TABLE IF NOT EXISTS `b` (
  `id_b` int(11) NOT NULL,
  `id_a` int(11) NOT NULL,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY  (`id_b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Where b.id_a is a foreign key to a.id_a

I want to get a hierarchy of all thoses like

A VALUE 1

  • b_value_1
  • b_value_2

A VALUE 2

  • b_value_11
  • b_value_12

A VALUE 3

  • b_value_21
  • b_value_22
  • b_value_23

The request doesn't matters but I get this kind of anwser:

VALUEOF-TABLE-A | VALUEOF-TABLE-B
A VALUE 1       | b_value_1
A VALUE 1       | b_value_2

and so on.

My current code is something like:

$categ = '';
while ($row = mysql_fetch_row ($ressource))
{
   if ($row['VALUEOF-TABLE-A']!=$categ) 
   { 
     $categ = $row['VALUEOF-TABLE-A']; 
     echo '<h3>', $categ, '</h3>';
   }
   echo '<h4>', $row['VALUEOF-TABLE-B'], '</h4>';
}

But I don't like much the idea of the categ variable, be it a string or an id. Is there an other way to get the data and display them?

Ideally, I'de like a tree object, having only one node for identical children.

Hope you understood what I want.

A: 

When working with foreign keys in Mysql, you should use the InnoDB engine instead of MyISAM.

There seems to be a problem in the conception of the b table, id_b should be the primary key, not id_a.

To solve your problem, maybe you should first retrieve the list of id_a, then make one selection request by id_a to select the corresponding id_b using a JOIN.

EDIT : the script should look like this with a little more presentation :

$category_array = mysql_query("SELECT id_a, type FROM a");
while ($category = mysql_fetch_array($category_array))
{
    echo $category['type'];
    $product_array = mysql_query("SELECT * FROM b WHERE id_a = $id_a");
    while ($product = mysql_fetch_array($product_array))
    {
         echo $product['name'];
    }
}
Michael Pereira
you are right, the key is id_b but I swaped the table order in my post and forgot this.The request is an implicit join : it's a kind of select a.name, b.type from table_a a, table_b b where a.id_a = b.id_a
Aif
I added a little script, I didn't tested it but the structure should be correct.
Michael Pereira
Yep thanks, this was the second solution I was speaking about (well actualy it seems that I didn't) but my aim was to perform this kind of things without doing a query for each category.
Aif
A: 

Any improvement ?

Michael Pereira
A: 

The example Chico gives is on the right track, but has a problem: when there are many categories, the script will also execute many queries, which is inefficient. The following example is much more efficient:

$categories = array();
$category_array = mysql_query("SELECT id_a, type FROM a");
while ($category = mysql_fetch_array($category_array))
{
    $category['products'] = array();
    $categories[$category['id_a']][] = $category;
}

$product_array = mysql_query("SELECT * FROM b");
while ($product = mysql_fetch_array($product_array))
{
    $categories[$product['id_a']]['products'][] = $product
}

foreach($categories as $category) {
    echo $category['type'];
    foreach ($category['products'] as $product) {
         echo $product['name'];
    }
}

As an added bonus, this also separates the retrieval of the data more cleanly from the output.

John
Thanks for replying, but I don't find it really better than my first idea.I think I should keep my first idea, and keep the previous category's id and a current-category-id variable and compare them.
Aif