简体   繁体   English

按类别对mysql结果进行分组,并将它们显示在每个类别下的组中

[英]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. 我正在尝试创建一个简单的css菜单,从mysql表中获取数据。

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". 每个链接都有一个名为“category”的字段。 So I want to group and display the links in the menu per category. 所以我想在每个类别的菜单中分组和显示链接。

I have mysql grouping like 我有mysql分组之类的

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

and then I have the html like this 然后我有像这样的HTML

<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 db表看起来像这样

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. 所以,我在将结果放入循环并按类别创建html时遇到了麻烦。

I read many posts here with similar content but couldn't achieve the result I wanted. 我在这里阅读了许多相似内容的帖子,但无法达到我想要的结果。 Any help will be much appreciated. 任何帮助都感激不尽。 Thanks! 谢谢!

I would use ORDER BY category instead. 我会改用ORDER BY category 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 原始选项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. 如果只想让每个父类别获得一次,则应该使用DISTINCT One should not use GROUP BY without using any aggregation function. 不使用任何聚合函数就不应该使用GROUP BY Combining GROUP BY with SELECT * is limited to (mostly) MySQL. GROUP BYSELECT *的组合仅限于(主要)MySQL。 You cannot select arbitrary columns in this case in ASNI SQL. 在这种情况下,您无法在ASNI SQL中选择任意列。

A variant of option 1 选项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 . 这是使用DISTINCT而不是GROUP BY的更正版本。

It still lacks of nested query calls. 它仍然缺乏嵌套查询调用。 For 5 parent categories, this leads to 5 queries in the loop. 对于5个父类别,这将导致循环中的5个查询。 For 10 parent categories, there are already 10 queries inside. 对于10个父类别,内部已有10个查询。 One should avoid this kind of growing in general. 人们应该避免这种增长。

Option 3 选项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. 数据库花费(简单查询)大部分时间来解析提供的SQL语句,并且只有一小部分时间来实际收集您请求的数据。 If you provide lots of SQL code, it has to spend a lot of time parsing it. 如果您提供了大量SQL代码,则必须花费大量时间来解析它。 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 尚未说明的选项4

There exists an until now unstated further solution. 存在一个直到现在未说明的进一步解决方案。 One can use prepared statements, prepare the SQL once and run it with different ids. 可以使用预准备语句,准备一次 SQL并使用不同的ID运行它。 This would still query all categories inside the loop, but would avoid the necessity to parse SQL code every time. 这仍然会查询循环内的所有类别,但是不必每次都解析SQL代码。

Actually I do not know if this is better or worse (or sth. in between) than my solution. 实际上我不知道这比我的解决方案更好还是更坏(或者介于两者之间)。

SQL GROUP BY statement groups the results so that only one row is returned for each category. SQL GROUP BY语句对结果进行分组,以便每个类别只返回一行。 This is typically used in conjunction with an aggregate function like count(), to count how many items are in each category. 这通常与count()之类的聚合函数结合使用,以计算每个类别中的项目数。 What you need is an either ORDER BY as GhostGambler said, or a separate query for each category as shown bellow. 你需要的是GhostGambler所说的ORDER BY ,或者如下所示的每个类别的单独查询。 However as you only seem to have 2 categories, this approach seems unnecessarily complicated. 然而,由于您似乎只有两个类别,这种方法似乎不必要地复杂化。

 $q=$db->query("SELECT DISTINCT category FROM content ORDER BY category");
 foreach($q as $cat){
    echo '<li id="'.$cat['category'].'" class="files">';  
    echo '<a href="'.$cat['category'].'">'.$cat['category'].'</a>'; 
    echo '<ul class="sub-menu">';
    $linkq=$db->query("SELECT * FROM content WHERE category='" . $cat['category'] . "'"); 
    foreach($linkq as $link){
       echo '<li><a href="#">'.$link['menu_name'].'</a></li>';
    }
    echo '</ul></li>';
 }

Your query is wrong 你的查询错了

$sql = "SELECT * FROM content WHERE group by category";

should be 应该

$sql = "SELECT * FROM content group by category";

Also since mysql is deprecated avoid using it. 此外,因为不推荐使用mysql而不使用它。 Use mysqli or PDO instead 请改用mysqli或PDO

I am assuming that you are wondering to add sub-menu dynamically. 我假设您想要动态添加子菜单。 If so then first create a 2nd table for sub-menu and add relationship between menu and sub-menu tables. 如果是,则首先为子菜单创建第二个表,并在菜单和子菜单表之间添加关系。

$select=$connection->query("select * from menus");
    while($result=$select->fetch_assoc()){
    echo "<li>";        
    echo "<a href=\"#\">".$result['MenuTitle']."</a>";
    $menuid=$result['MenuId'];
    if($result==true){
    $selectsubmenu=$connection->query("Select * from submenu where menuid='$menuid'");
        echo "<ul>";
            while($resultsubmenu=$selectsubmenu->fetch_assoc()){     
                    echo "<li><a href=\"Services.php?submenu=".$resultsubmenu['SubMenuId']."\">".$resultsubmenu['SubMenuTitle']."
                    </a></li>";
                    }
        echo "</ul>";
                }
            echo "</li>";   
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM