Detta borde göra susen:
$result = mysql_query("SELECT * FROM News");
$topicname = '';
// open list of topics
echo '<ul>';
// loop through topics
while($row = mysql_fetch_array($result)) {
if (!$row['TopicID']) {
// fake topic name for unsorted stuff
$row['TopicName'] = 'Sort Me';
}
if ($topicname != $row['TopicName']) {
if($topicname != ''){
// had a topic name, means we opened a list
// that hasn't been closed, close it.
echo '</ul>';
}
// print this topic and open the list of articles
echo '<li>' . $row['TopicName'] . '</li><ul>';
// update the current topic to be this TopicName
$topicname = $row['TopicName'];
}
// the news item
echo '<li>' . $row['NewsID'] . '"</li>';
}
if($topicname != ''){
// we saw at least one TopicName, we need to close
// the last open list.
echo '</ul>';
}
// end topic list
echo '</ul>';
Jag tror att ditt verkliga problem är att du öppnade två listor varje gång, men bara stängde en (till och med flyttade det sista blocket i listan).
För den andra delen av din (nya) fråga:
Jag förbehåller mig att för större listor (säg mer än 300 objekt) skulle den avvägning jag gör med avseende på att lagra listan i minnet och iterera två gånger istället för att bara fråga efter det antal som behövs, ändras åt andra hållet. Det vill säga, lösningen nedan lägger in allt i minnet och upprepar sedan en andra gång för att skriva ut det; ett alternativ skulle vara att köra två frågor, en för att hitta antalet unika ämnesnamn och en för att hitta det totala antalet objekt i listan.
Dessutom, för visning, du verkligen vill lösa lite optimering för layout, jag kommer att göra detta naivt och bara göra ett (ungefär) lika antal ämnen per kolumn och när uppdelningen inte fungerar kommer detta att väga åt vänster. Du kommer att se var du kan justera eller ersätta en del kod för att få andra (och bättre?) resultat.
$columns = // user specified;
$result = mysql_query("SELECT * FROM News");
$num_articles = 0;
// $dataset will contain array( 'Topic1' => array('News 1', 'News2'), ... )
$dataset = array();
while($row = mysql_fetch_array($result)) {
if (!$row['TopicID']) {
$row['TopicName'] = 'Sort Me';
}
$dataset[$row['TopicName']][] = $row['NewsID'];
$num_articles++;
}
$num_topics = count($dataset);
// naive topics to column allocation
$topics_per_column = ceil($num_topics / $columns);
$i = 0; // keeps track of number of topics printed
$c = 1; // keeps track of columns printed
foreach($dataset as $topic => $items){
if($i % $topics_per_columnn == 0){
if($i > 0){
echo '</ul></div>';
}
echo '<div class="Columns' . $columns . 'Group' . $c . '"><ul>';
$c++;
}
echo '<li>' . $topic . '</li>';
// this lists the articles under this topic
echo '<ul>';
foreach($items as $article){
echo '<li>' . $article . '</li>';
}
echo '</ul>';
$i++;
}
if($i > 0){
// saw at least one topic, need to close the list.
echo '</ul></div>';
}