Группировка mysql по категориям и отображение их в группы по каждой категории

Я пытаюсь создать простое меню css, которое получает данные из таблицы mysql.

Моя идея – иметь такое меню

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

каждая ссылка имеет поле под названием «категория». Поэтому я хочу группировать и отображать ссылки в меню для каждой категории.

У меня есть mysql grouping like

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

и тогда у меня есть 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> 

Таблица 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'); 

Таким образом, у меня возникают проблемы, которые помещают результаты в цикл и создают html по категориям.

Я читал много сообщений здесь с похожим контентом, но не смог добиться желаемого результата. Любая помощь будет высоко ценится. Благодаря!

Вместо этого я бы использовал ORDER BY category . Затем вы можете повторить набор результатов, например

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

Обновить

До сих пор в этой теме существует три возможных решения самой проблемы.

Исходный вариант 1

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

Если вы хотите получить только одну родительскую категорию один раз, вместо этого следует использовать DISTINCT . Нельзя использовать GROUP BY без использования какой-либо функции агрегации. Объединение GROUP BY с SELECT * ограничено (в основном) MySQL. Вы не можете выбрать произвольные столбцы в этом случае в ASNI SQL.

Вариант варианта 1

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

Это исправленная версия с DISTINCT вместо GROUP BY .

Он по-прежнему не имеет вложенных запросов. Для 5 родительских категорий это приводит к 5 запросам в цикле. Для 10 родительских категорий внутри уже есть 10 запросов. Следует избегать такого рода роста в целом.

Вариант 3

 SELECT * FROM content ORDER BY category, menu_name 

можно использовать с приведенным выше кодом.

Это предпочтительнее других вариантов, показанных по разным причинам:

  • Вам нужен только один запрос базы данных для сбора всех данных одновременно. База данных тратит (на простые запросы) большую часть своего времени, анализируя предоставленный SQL-оператор, и только часть времени фактически собирает запрошенные вами данные. Если вы предоставляете много кода SQL, он должен потратить много времени на его синтаксический анализ. Если вы предоставляете меньше кода, это меньше.
  • Для базы данных проще получить данные один раз, отсортировать их один раз и вернуть их вам один раз, вместо того, чтобы собрать часть, отсортировать часть, вернуть часть и начать все заново.

еще не установлен вариант 4

Существует до сих пор неустановленное дальнейшее решение. Можно использовать подготовленные операторы, подготовить SQL один раз и запустить его с разными идентификаторами. Это все равно будет запрашивать все категории внутри цикла, но будет избегать необходимости каждый раз анализировать SQL-код.

На самом деле, я не сейчас, если это лучше или хуже (или между прочим), чем мое решение.

Оператор SQL GROUP BY группирует результаты так, чтобы для каждой категории возвращалась только одна строка. Обычно это используется вместе с агрегированной функцией, такой как count (), для подсчета количества элементов в каждой категории. Что вам нужно, либо ORDER BY как сказал GhostGambler, или отдельный запрос для каждой категории, как показано ниже. Однако, поскольку у вас есть только 2 категории, этот подход кажется излишне сложным.

  $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>'; } 

Ваш запрос неверен

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

должно быть

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

Кроме того, поскольку mysql устарел, не используйте его. Вместо этого используйте mysqli или PDO

Я предполагаю, что вам интересно добавить динамическое подменю. Если это так, сначала создайте вторую таблицу для подменю и добавьте связь между таблицами меню и подменю.

 $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>"; } в $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>"; } в $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>"; }