[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Вывод данных в иерархической последовательности
kirik
Имеем таблицу
comments { comment_id | parent_id | post_id | author_id | text | date }

Собственно нужен запрос (если такой возможен), который выведет все комменты в иерархической последовательности к определенному посту (post_id)

Читал это, но там описывается не совсем то, что нужно.

Хочется обойтись без использования циклов, по возможности.. =)



Спустя 3 часа, 22 минуты, 37 секунд (22.12.2008 - 11:34) kirik написал(а):
пока самый быстрый и простой вариант для меня - вывести все комменты с нужным post_id сортируя по полю date, а затем применить что-то типа этого:

PHP
$arr = array(
    array('id'=>1, 'pid'=>0), 
    array
('id'=>2, 'pid'=>1), 
    array
('id'=>3, 'pid'=>1), 
    array
('id'=>4, 'pid'=>2), 
    array
('id'=>5, 'pid'=>2), 
    array
('id'=>6, 'pid'=>1), 
    array
('id'=>7, 'pid'=>2), 
    array
('id'=>8, 'pid'=>0), 
);

for(
$i = 0, $c = count($arr); $i < $c; $i++)
{
    $pid = ($arr[$i]['pid'] == 0) ? $arr[$i]['id'] : $arr[$i]['pid'];
    $new_arr[$pid][$arr[$i]['id']] = $arr[$i];
}
echo '<pre>';
print_r($new_arr);
echo '</pre>';


UPD
блин... не совсем то что нужно..пойду просплюсь =)

Спустя 3 часа, 21 минута, 14 секунд (22.12.2008 - 14:56) FatCat написал(а):
Задача не решается правильной последовательностью критериев order by в запросе?

Спустя 6 минут, 2 секунды (22.12.2008 - 15:02) Alchemist написал(а):
гм... я не совсем уверен, что понял как надо, но почему не достаточно отсортировать по дате и собирать через
PHP
$new_arr$row['parent_id'] ][] = $row;


Соответственно комменты верхнего уровня будут лежать в $new_arr[0], а комменты к комментам в $new_arr[ $comment['comment_id'] ]...

Спустя 29 минут, 58 секунд (22.12.2008 - 15:32) FatCat написал(а):
Для примера:

Есть таблица с полями:
  • rid - айдишник по инкременту;
  • time - собственно, php_time();
  • post_id - за кого голосовали;
  • voter_id - кто проголсовал;
  • ball - оценка при голосовании.
Один голосовавший может подать несколько голосов за один объект голосования

SQL
SELECT * FROM ibf_posts_ratio WHERE time > ".$time_start." AND time < ".$time_end." ORDER BY post_id, voter_id, rid

На выходе имеем отчет за интервал времени: отсортирован по объектам голосований; внутри объекта сортировка по голосовавшим; внутри голосовавших оценки сортированные по дате.



Спустя 7 минут, 52 секунд FatCat написал(а):
Дальше в цикле наводим красоту: по полям post_id и voter_id сравниваем значение с предыдущим, и при совпадении выводим в ячейку таблицы пробел; на выходе имеем красивую табличку:
user posted image




Спустя 11 минут, 16 секунд FatCat написал(а):
Вот, собственно, сам код:
PHP
$post_id = "";$voter_name = "";
        $DB->query("SELECT * FROM ibf_posts_ratio WHERE time > ".$time_start." AND time < ".$time_end." ORDER BY post_id, voter_id, rid");
        while ( $r = $DB->fetch_row() )
        {
            if($post_id != $r['post_id'])$a[0] = "Сообщение #<a href='".$INFO['board_url']."/index.php?showtopic=0&view=findpost&p=".$r['post_id']."' target='_blank'>".$r['post_id']."</a>";
            else $a[0] = "&nbsp;";
            
            if
($voter_name != $r['voter_name'] or $post_id != $r['post_id'])$a[1] = "<a href='".$INFO['board_url']."/index.php?showuser=".$r['voter_id']."' target='_blank'>".$r['voter_name']."</a>";
            else $a[1] = "&nbsp;";
            
            $a
[2] = "".$r['ball'];
            
            $a
[3] = "".$r['vote_text'];
            
            $a
[4] = $std->get_date( $r['time'], 'LONG' );
            
            $voter_name 
= $r['voter_name'];$post_id = $r['post_id'];
            $a[5] = $SKIN->form_checkbox("rid_".$r['rid'], 0);
            
            $ADMIN
->html .= $SKIN->add_td_row($a);
        }

Спустя 15 минут, 5 секунд (22.12.2008 - 15:47) Alchemist написал(а):
FatCat, насколько я понял ему надо иерархию, когда я могу поставить оценку не только объекту, но и твоей оценке, и он хочет их вынуть в виде дерева, как (например) комменты в ЖЖ.

ЗЫ: и еще одно... пожалуйста, ПОЖАЛУЙСТА, П-О-Ж-А-Л-У-Й-С-Т-А, перестань использовать слово "ball" в качестве "балла"! Меня просто плющит каждый раз как вижу это...

Я уже привык, что народ смешивает русский и английский в названиях, но одно дело видеть "soobschenie" пядом с "voter", и совсем другое "ball" - это слово таки да имеет значение в английском, и совсем не то, которое ты в него вкладываешь... Если тебе надо слово для "оценки": grade, mark, value, points...

ЗЗЫ: у тебя одинарные кавычки удвоились в коде...

Спустя 2 часа, 52 минуты (22.12.2008 - 18:39) FatCat написал(а):
Цитата (Alchemist @ 22.12.2008 - 15:47)
перестань использовать слово "ball" в качестве "балла"!

Не могу, это навеки прописано в БД. laugh.gif

Я в школе учил немецкий, в институте латынь и немного греческого; знали бы вы только, какие ассоциации иногда вызывают английские слова... rolleyes.gif


Цитата (Alchemist @ 22.12.2008 - 15:47)
у тебя одинарные кавычки удвоились в коде...

Опять беда с этим модом подсветки синтаксиса...
Сейчас помудрю, чтобы при редактировании сообщения кавычки не размножались...

Спустя 4 часа, 18 минут, 42 секунды (22.12.2008 - 22:57) kirik написал(а):
Цитата (Alchemist @ 22.12.2008 - 07:02)
гм... я не совсем уверен, что понял как надо, но почему не достаточно отсортировать по дате и собирать через
PHP
$new_arr[ $row['parent_id'] ][] = $row;

Это не совсем то что нужно.. здесь будет только один уровень, а может быть так -

PHP
Коммент 1 [2 cентября]
    
Коммент 1.1 [2 cентября]
    
Коммент 1.2 [3 cентября]
        
Коммент 1.2.1 [4 cентября]
            
Коммент 1.2.1.1 [20 cентября]    
            
Коммент 1.2.1.1 [21 cентября]    
        
Коммент 1.2.2 [10 cентября]

причем тут же можно увидеть почему нельзя просто сортировать комменты по дате добавления.

FatCat, это не совсем то, как нужно вывести комменты

Цитата (Alchemist @ 22.12.2008 - 07:47)
он хочет их вынуть в виде дерева, как (например) комменты в ЖЖ.

+++

Цитата (FatCat @ 22.12.2008 - 10:39)
Опять беда с этим модом подсветки синтаксиса...

незнаю, может чем-то поможет -
http://www.php.su/articles/?cat=examples&page=058

Спустя 1 час, 31 минута, 29 секунд (23.12.2008 - 00:29) FatCat написал(а):
Цитата (kirik @ 22.12.2008 - 22:57)
это не совсем то, как нужно вывести комменты

Не вижу принципиальной разницы. unsure.gif


Цитата (kirik @ 22.12.2008 - 22:57)
может чем-то поможет -
http://www.php.su/articles/?cat=examples&page=058

Это я видел. Примерно это и использовал.

Проблема в конфликте с системой безопасности ББ-кодов.
Не случайно же приличного мода подсветки нет ни на одном форуме.
Функция highlight_string символы кавычек, амперсандов, $ и т.д., а не их метасимволы.
В форуме разрешить эти символы смерти подобно - живо найдется умник, который проведет sql-инъекцию.
Поэтому ВСЕ входящие на форум парсятся при входе на метасимволы.
Для подсветки кодов приходится сначала вычленить содержимое контейнера [ php ], затем распарсить метасимволы в символы, затем скормить их функции highlight_string, затем обратно отпарсить в метасимволы...

Дополнительная беда: highlight_string проверяет наличие в коде <%, и только если их нет, добавляет; если же есть - не добавляет.
Причем, игнорирует предшествующие пробелы, табуляторы, переводы строк...

В общем, засады на каждом шагу...

Спустя 1 час, 36 минут, 6 секунд (23.12.2008 - 02:05) kirik написал(а):
Цитата (FatCat @ 22.12.2008 - 16:29)
Не вижу принципиальной разницы. unsure.gif


По вашему алгоритму - соритруем комменты по id , затем по родительскому id, и потом по дате добавления. что получим?

{comment_id}(parent_id)

PHP
{1}(0) Коммент 1 [2 cентября]
    {2}(1) Коммент 1.1 [2 cентября]
    {3}(1) Коммент 1.2 [3 cентября]
        {4}(3) Коммент 1.2.1 [4 cентября]
//             {6}(4) Коммент 1.2.1.1 [20 cентября]    
//             {7}(4) Коммент 1.2.1.2 [21 cентября]  
         {5}(3) Коммент 1.2.2 [10 cентября]
            {6}(4) Коммент 1.2.1.1 [20 cентября]    
            
{7}(4) Коммент 1.2.1.2 [21 cентября]

как-то так.. или я вас не правильно понял...

нужно -
PHP
{1}(0) Коммент 1 [2 cентября]
    {2}(1) Коммент 1.1 [2 cентября]
    {3}(1) Коммент 1.2 [3 cентября]
        {4}(3) Коммент 1.2.1 [4 cентября]
            {6}(4) Коммент 1.2.1.1 [20 cентября]    
            
{7}(4) Коммент 1.2.1.2 [21 cентября]    
        
{5}(3) Коммент 1.2.2 [10 cентября]


Цитата (FatCat @ 22.12.2008 - 16:29)
Дополнительная беда: highlight_string проверяет наличие в коде <%, и только если их нет, добавляет; если же есть - не добавляет.

Можно попробовть вырезать гланды автогеном через *Ж* =)
Как известно, если файл переименовать из .php в .phps , то в браузер выведется подсвеченный код.
Алгоритм - вытаскиваем из бокса [ php] весь код => переводим его из метасимволов в нормальные символы => создаем темп файл с расширением .phps в доступной из сети папке => записываем в него содержимое бокса => через курл(или другим способом) вызываем его => удаляем темп файл => забираем полученый результат ввиде раскрашенного кода + переводим некоторые символы в метасимволы =)

если есть доступ к командной строчке, то можно обойтись без курла =)

С таким способом не будет нехорошей траблы с <%

UPD
кстати можно заменять <% например на %REPLACE123%, а после обработки функцией highlight_string заменять обратно, чтобы не смущать ее.=)

Спустя 39 минут, 47 секунд (23.12.2008 - 02:45) FatCat написал(а):
То есть, степеней ветвления по parent_id может быть больше, чем одна?
Решал раз такую задачу через псевдомассив в строковой переменной.
Запрос сортируется в порядке возрастания parent_id. Затем в цикле заполняются строки.
Идея в том, что каждая строка содержит как бы всю историю parent_id-ов одного айдишника.
Затем эксплодим эту переменную, и полученный массив пересортировываем.


Цитата (kirik @ 23.12.2008 - 02:05)
Можно попробовть вырезать гланды автогеном через *Ж* =)

На самом деле, надо найти время и просто написать комплект регулярок, корректно работающих с ББ-кодами.

Для меня задача подсветки кода не очень приоритетна, поэтому вряд ли до нее доберусь в ближайшее время.
Но можно открыть топик, где общими силами будем писать эти регулярки.

Спустя 13 минут, 35 секунд (23.12.2008 - 02:58) kirik написал(а):
Цитата (FatCat @ 22.12.2008 - 18:45)
То есть, степеней ветвления по parent_id может быть больше, чем одна?

Да, их может быть неограниченное количество

Цитата (FatCat @ 22.12.2008 - 18:45)
Идея в том, что каждая строка содержит как бы всю историю parent_id-ов одного айдишника.

А вот это интересно.. Подумаю в этом направлении..

Цитата (FatCat @ 22.12.2008 - 18:45)
Но можно открыть топик, где общими силами будем писать эти регулярки.

Почему нет? =) По возможности опишите подробнее проблемы которые есть сейчас.

Спустя 5 минут, 31 секунда (23.12.2008 - 03:04) Alchemist написал(а):
Цитата (kirik @ 22.12.2008 - 21:57)
Это не совсем то что нужно.. здесь будет только один уровень, а может быть так -

ты не прав.
фактически у тебя действительно получается всего лишь двухуровневый массив, но он моментально переделывается в дерево.

Вот простой пример:
PHP
<?
// такой массив ты получишь из БД. Каждый элемент это массив вида {commecnt_id, name}
$db_data = array(
    0 => array( 
          array
(1, 'Коммент 1')
    ),
    1 => array(
          array(11, 'Коммент 1.1')
        , array(12, 'Коммент 1.2')
    ),
    12 => array(
          array(121, 'Коммент 1.2.1')
        , array(122, 'Коммент 1.2.2')
    ),
    121 => array (
          array(1211, 'Коммент 1.2.1.1')
        , array(1212, 'Коммент 1.2.1.2')
    )
);

function db_line(&$data, $parent, $level)
{
    $arr = $data[$parent];
    for($i=0; $i<count($arr); $i++) {
        echo '<span style="padding-left:'.($level*10).'px">'.$arr[$i][1].'</span><br />';
        if (count($data[$arr[$i][0]]))
            db_line($data, $arr[$i][0], $level + 1);
    }
}

db_line($db_data, 0, 0);

Спустя 40 минут, 10 секунд (23.12.2008 - 03:44) kirik написал(а):
Alchemist, я бы даже сказал что он и практически тоже двухуровневый.. =) Все круто работает! Вроде не особо сложно, а завалился.. =)

Спасибо вам Большое Alchemist и FatCat!!

Результат, если кому нужен будет:
PHP
function db_line($data$parent=0$level=0)
{
    
$arr $data[$parent];

    for(
$i 0$i count($arr); $i++)
    {
        echo 
'<span style="padding-left:'.($level*30).'px">'.$arr[$i]['name'].'</span><br />';
        if(
count($data[$arr[$i]['id']]))
            
db_line($data$arr[$i]['id'], $level 1);
    }
}


$arr = array(
    array(
'id'=>1'pid'=>0'name'=>'Comment 1'), 
        array(
'id'=>2'pid'=>1'name'=>'Comment 1.1'), 
            array(
'id'=>4'pid'=>2'name'=>'Comment 1.1.1'), 
            array(
'id'=>5'pid'=>2'name'=>'Comment 1.1.2'), 
            array(
'id'=>7'pid'=>2'name'=>'Comment 1.1.3'), 
        array(
'id'=>3'pid'=>1'name'=>'Comment 1.2'), 
        array(
'id'=>6'pid'=>1'name'=>'Comment 1.3'), 
    array(
'id'=>8'pid'=>0'name'=>'Comment 2'), 
);

for(
$i 0$c count($arr); $i $c$i++)
{
    
$new_arr[$arr[$i]['pid']][] = $arr[$i];
}

db_line($new_arr);


Вывод: забиваем на SQL запрос, и делаем циклом =)

Спустя 22 минуты, 8 секунд (23.12.2008 - 04:06) FatCat написал(а):
Цитата (kirik @ 23.12.2008 - 02:05)
Как известно, если файл переименовать из .php в .phps , то в браузер выведется подсвеченный код.
Алгоритм - вытаскиваем из бокса [ php] весь код

Гы!
Есть решение, простое, как 3 копейки!
Заливаем в файл *phps и выводим ифреймом. Заодно проблема больших листингов длинных кодов автоматом решится скроллингами ифрейма.

Надо почитать, нет ли риска запуска такого файла исполняемым...

Спустя 41 минута, 55 секунд (23.12.2008 - 04:48) kirik написал(а):
Цитата (FatCat @ 22.12.2008 - 20:06)
Заодно проблема больших листингов длинных кодов автоматом решится скроллингами ифрейма.

также эти большие листниги не будут засорять базу =)

Цитата (FatCat @ 22.12.2008 - 20:06)
Надо почитать, нет ли риска запуска такого файла исполняемым...

Если насильно через htaccess не прописывать, то не должен выполнятся.

Спустя 8 часов, 38 минут, 51 секунда (23.12.2008 - 13:27) FatCat написал(а):
Цитата (kirik @ 23.12.2008 - 04:48)
также эти большие листниги не будут засорять базу =)

В любом случае не будут.
PHP
if(strlen($this->post['post']) > 4000){
// Несколько строк кода сгрызли мыши
$std->create_archived_post($this->post['pid'], "arc"$this->post['post']);


PHP
function create_archived_post($pid$j_type$txt)
    {
        
$arc_path = ($pid-$pid%1000)/1000;
        
$arc_path "../arc/".$arc_path."/";
        
$arc_file $pid%1000;
        
$arc_file $arc_path.$arc_file.".".$j_type;
        if(
file_exists($arc_file))unlink($arc_file);
        if(
$txt != "")
        {
            if(!
file_exists($arc_path))mkdir($arc_path0777);
            
$fh fopen($arc_file"w");
            
fwrite($fh$txt);
            
fclose($fh);
        }
    }



Идея открывать код в ифрейме мне все больше и больше нравится.
Правда, попотеть придется: для работы предпросмотра и для возможности редактирования/удаления сообщений, потребуется написать пару функций, управляющих phps-файлами.

Спустя 9 часов, 53 минуты, 21 секунда (23.12.2008 - 23:20) Гость написал(а):
А если несколько листингов в сообщении.. ведь это нужно будет получить такое же количество файлов.
А проблема больших листингов - не проблема, в textarea так же можно перематывать код..

Так стоит ли оно того..

Спустя 18 минут, 24 секунды (23.12.2008 - 23:39) FatCat написал(а):
Цитата (Гость @ 23.12.2008 - 23:20)
проблема больших листингов - не проблема, в textarea так же можно перематывать код..

Несомненно.
Но красить в текстарее...

А вот несколько файлов - это совсем не проблема.

Спустя 29 минут, 39 секунд (24.12.2008 - 00:08) FatCat написал(а):
Удалил сообщение вместе с тестовым механизмом сброса в файлы.
Красива была идея, но слишком много подводных каменй...

Спустя 17 минут, 44 секунды (24.12.2008 - 00:26) kirik написал(а):
Цитата (FatCat @ 23.12.2008 - 16:08)
Удалил сообщение вместе с тестовым механизмом сброса в файлы.

На самом деле какой смысл сбрасывать сообщения в файлы..? Это не должно никак влиять на БД, кроме увеличения размера.. выборка производится по id-шным полям, а эти просто мертвым грузом лежат себе в такомже файле БД, только большом, и все вместе..=)
Работал с большим проектом онлайн аукциона (на ASP+mysql) так разработчики решили все файлы (в т.ч и оформление) они хранить в БД.. на скорость конечно влияло, но, нада сказать, не критично..=)

Спустя 19 минут, 22 секунды (24.12.2008 - 00:45) kirik написал(а):
Очередной вопрос мучает...

Та же самая таблица, те же связи. Как удалить коммент, и весь тред со связями?

PHP
{1}(0) Коммент 1 [2 cентября]
    {2}(1) Коммент 1.1 [2 cентября]
    {3}(1) Коммент 1.2 [3 cентября]
        {4}(3) Коммент 1.2.1 [4 cентября]
            {6}(4) Коммент 1.2.1.1 [20 cентября]    
            
{7}(4) Коммент 1.2.1.2 [21 cентября]    
        
{5}(3) Коммент 1.2.2 [10 cентября]

Удаляем коммент 1.2 с ним должны потереться 1.2.1, 1.2.1.1 и 1.2.1.2.
Опять также через цикл (собираем все id и удаляем с помощью IN()), или есть другой способ?

Спасибо!

PS Родительские id-шники одинаковые только у тех комментов, которые стоят на одном уровне.

Спустя 2 часа, 37 минут, 7 секунд (24.12.2008 - 03:22) FatCat написал(а):
Цитата (kirik @ 24.12.2008 - 00:45)
(собираем все id и удаляем с помощью IN()), или есть другой способ?

Прямо в цикле и удалять поодиночке.
Если помнишь, совсем недавно столкнулся с дикими тормозами при удалении группой: http://hardapple.ru/index.php?showtopic=14715

Спустя 41 минута, 16 секунд (24.12.2008 - 04:04) kirik написал(а):
Да, помню такую засаду.. только я не думаю что подкомментов будет очень много =)
Хотя че парится.. не будут же каждые 2 секунды удалять по 1000 комментов.. можно и в цикле..=)

Спасибо!
наверно тему можно закрывать..=)

Спустя 4 дня, 22 часа, 5 минут, 50 секунд (29.12.2008 - 02:10) Сеня написал(а):
Вот нарвался как раз, если кому интересно, - почитайте про "деревья":
1. http://habrahabr.ru/blogs/development/46659/
2. http://habrahabr.ru/blogs/development/47280/

Спустя 13 часов, 48 минут, 50 секунд (29.12.2008 - 15:58) Alchemist написал(а):
вот именно ради таких постов я и сижу на этом форуме

Спустя 2 года, 6 месяцев, 7 дней, 9 часов, 2 минуты, 49 секунд (7.07.2011 - 00:01) tatti написал(а):
kirik
насколько понимаю нужен выбор подчиненных узлов?
в nested sets это есть. может стоит повзаимствовать оттуда
SELECT id, name, level FROM my_tree WHERE left_key >= $left_key AND right_key <= $right_key ORDER BY left_key
правда прийдётся несколько изменить структуру таблицы....
взято тут
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.