Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
268 views
in Technique[技术] by (71.8m points)

php - Group mysql results by category and display them into groups under each category

I am trying to create a simple css menu that gets the data from a mysql table.

My idea is to have menu like this

    Category 1
    - link 1
    - link 2
    - link 3
    Category 2
    - link 1
    - link 2
    - ect...

every link has a field named "category". So I want to group and display the links in the menu per category.

I have mysql grouping like

$sql = "SELECT * FROM content group by category";
$result = mysql_query($sql); 

and then I have the html like this

<ul class="menu">
    <li id="category1" class="files">
         <a href="#category1">Category 1</a>
         <ul class="sub-menu">
             <li><a href="#">link 1</li>
             <li><a href="#">link 2</li>
             <li><a href="#">link 3</li>
         </ul>
     </li>
    <li id="category2" class="files">
         <a href="#category2">Category 2</a>
         <ul class="sub-menu">
             <li><a href="#">link 1</li>
             <li><a href="#">link 2</li>
             <li><a href="#">link 3</li>
         </ul>
     </li>
 </ul>

The db table looks like this

CREATE TABLE IF NOT EXISTS `content` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `menu_name` text,
  `menu_name_en` text,
  `menu_url` varchar(255) NOT NULL DEFAULT '',
  `header_name` text,
  `header_name_en` enum('MEDIA','GENERAL') NOT NULL DEFAULT 'MEDIA',
  `text` longtext NOT NULL,
  `text_en` text,
  `category` enum('Category 1', 'Category 2') NOT NULL DEFAULT 'Category 1',
  `date` date NOT NULL DEFAULT '0000-00-00',
  `visible` char(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
);

INSERT INTO content (id, menu_name, menu_name_en, menu_url, header_name, header_name_en, text, text_en, category, date, visible) VALUES (26, 'test name', '', 'test_url', 'test name', '', '<p>test text</p>', '<p>text text</p>', 'MEDIA', '2014-02-23', '1');

So, I am having troubles putting the results in the loop and creating the html by category.

I read many posts here with similar content but couldn't achieve the result I wanted. Any help will be much appreciated. Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I would use ORDER BY category instead. You can then iterate the result set like

$old = null;
foreach ($st as $s) {
  if $old != $s['id']
    echo 'Main category';
    $old = $s['id'];
  echo 'subcategory'

Update

There exist three possible solutions until now in this thread to the problem itself.

Original option 1

SELECT * FROM content group by category
foreach
  SELECT * FROM content WHERE category=$cat['category']

If one does only want to get each parent category once, one should use DISTINCT instead. One should not use GROUP BY without using any aggregation function. Combining GROUP BY with SELECT * is limited to (mostly) MySQL. You cannot select arbitrary columns in this case in ASNI SQL.

A variant of option 1

SELECT DISTINCT category FROM content ORDER BY category
foreach
  SELECT * FROM content WHERE category=$cat['category']

This is the corrected version with DISTINCT instead of GROUP BY.

It still lacks of nested query calls. For 5 parent categories, this leads to 5 queries in the loop. For 10 parent categories, there are already 10 queries inside. One should avoid this kind of growing in general.

Option 3

SELECT * FROM content ORDER BY category, menu_name

usable with the code above.

This is preferable to the other options shown due to different reasons:

  • You only need one single database query to gather all data at once. The database spends (on easy queries) most of its time parsing the SQL statement one provided and only a fraction of time to actually gather the data you requested. If you provide lots of SQL code, it has to spend a lot of time parsing it. If you provide less code, it has less to do.
  • It is easier for a database to get the data once, sort it once and return it to you once, instead of gather a part, sort a part, return a part and start all over again.

still unstated option 4

There exists an until now unstated further solution. One can use prepared statements, prepare the SQL once and run it with different ids. This would still query all categories inside the loop, but would avoid the necessity to parse SQL code every time.

Actually I do not know if this is better or worse (or sth. in between) than my solution.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...