Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Вывод данных из БД в несколько колонок (каталог)

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Требуется усовершенствование скрипта вывода данных из БД в несколько колонок
unambigos
Отправлено: 09 Декабря, 2011 - 14:44:20
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




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

CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. <style>
  3. .column{
  4.    float:left;
  5.    margin-right: 30px;
  6.    width: 300px;
  7. }
  8.  
  9. .column ul{
  10.    list-style-type: none;
  11.    background: #f6f6f6;
  12.    border: 1px dotted gray;
  13.    padding:5px;
  14. }
  15. </style>
  16.  
  17. <?php
  18.  
  19. //подключение к базе
  20. @mysql_connect("localhost","12345","12345") or die("Ошибка подключения к базе MySQL!");
  21. @mysql_select_db("example") or die("Ошибка подключения к базе данных");
  22.  
  23. //выборка пунктов 1-го уровня каталога
  24. @$res1 = mysql_query("SELECT id FROM catalog WHERE parent=0");
  25. @$myarray1 = mysql_fetch_array($res1);
  26.  
  27. $num = 0;
  28.  
  29. //цикл подсчета общего количества записей 2-го уровня
  30. do
  31. {
  32.    @$res3 = mysql_query("SELECT id FROM catalog WHERE parent='".$myarray1['id']."'");
  33.    $num += mysql_num_rows($res3);        
  34. }
  35. while ($myarray1= mysql_fetch_array($res1));
  36.  
  37. //опять выборка пунктов 1-го уровня каталога
  38. @$res = mysql_query("SELECT id,name FROM catalog WHERE parent=0");
  39. @$myarray = mysql_fetch_array($res);
  40.  
  41. $cols = 2; //число колонок
  42. $str = ceil($num/$cols); //округление в большую сторону числа строчек в одной колонке
  43. $j = 0; //обнуление счетчика
  44. for($i=1;$i<=$cols;$i++) //цикл счетчика колонок
  45. {
  46.  
  47.    
  48.    $content = "<div class='column'>";
  49.        //цикл вывода пунктов 1-го уровня каталога
  50.        do
  51.        {
  52.            
  53.            
  54.            $content.="<h3>".$myarray['name']."</h3><ul>";
  55.            @$res2 = mysql_query("SELECT name FROM catalog WHERE parent='".$myarray['id']."'");
  56.            @$myarray2 = mysql_fetch_array($res2);
  57.  
  58.                 //цикл вывода пунктов 2-го уровня каталога
  59.                do
  60.                {  
  61.                    if($myarray['id']){
  62.                   $content.="<li>".$myarray2['name']."</li>";
  63.                   $j++;
  64.                   }
  65.                }
  66.                while($myarray2 = mysql_fetch_array($res2));
  67.            $content.="</ul>";
  68.          
  69.        }
  70.        while($myarray = mysql_fetch_array($res) AND $j<$str);
  71.        
  72.    $content.="</div>";
  73.    if($str<$num)$str+=ceil($num/$cols);        
  74.    
  75.    echo $content;
  76. }
  77.  
  78.  
  79. ?>
  80.  



Пробовал использовать в цикле подсчета общего количества записей 2-го уровня запись вида SELECT COUNT(*) FROM catalog WHERE parent=.$myarray1['id']. - не работает, считает непонятно чего, но точно не количество записей.

Таблица в БД имеет следующий вид: /id/name/parent все записи каталога хранятся в ней где в поле parent указан id родительского элемента.

Есть предположение что вместо запросов внутри цикла нужно использовать конструкцию inner join. Но я перешарил весь интернет и так и не нашел руководства как этой конструкцией пользоваться. Я новичек в этих делах, так что сильно не ругайте. Надеюсь на Ваш профессионализм и помощь.

(Отредактировано автором: 09 Декабря, 2011 - 14:57:56)

 
 Top
caballero
Отправлено: 09 Декабря, 2011 - 15:32:07
Post Id


Активный участник


Покинул форум
Сообщений всего: 5998
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




Цитата:
нужно использовать конструкцию inner join.

это просто join. по сути то же что в where таблицы перевязать

Цитата:
Я новичек в этих делах, так что сильно не ругайте

нет ничего дебильнее подобной фразы на форумах


если по существу - классическая проблемма выборки иерапррхических данных

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

В твоем случае лучше всего выгрести простым селектом всю таблицу в массив а потом бегать по нему тем же циклом
Не очень гармоничное решение но все же лучше чем ходить циклом к БД.


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
unambigos
Отправлено: 09 Декабря, 2011 - 15:48:35
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




По поводу извлечь все данные в массив, я тоже уже думал, ну это ладно когда записей 500, а когда их 50000? Сможет ли выборка перебором массива обеспечить нужное быстродейтвие? Тем более, что с разными условиями его несколько раз прогонять нужно будет?

Цитата:
по уму - надо добавлять дополнительные поля с уровнями вложености или иписком парентов с строке


Можешь подробнее об этом. Мысль такая была, но потом я подумал, а как эту вложенность высчитывать потом, когда он будет может 8-12 пунктов, не будешь же всю таблицу штудировать. Блин, а так мысль хорошая извлечь все поля с уровнем вложенности 2 например. А потом полученный массив уже циклами мучить? Правильно я понял?

(Отредактировано автором: 09 Декабря, 2011 - 15:54:34)

 
 Top
unambigos
Отправлено: 10 Декабря, 2011 - 10:25:53
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




И кстати, кто нибудь может объяснить как пользоваться конструкцией JOIN. Или ссылочку, где написано как пользоваться. Только не для объединения разных таблиц, а для выборки из одной.
 
 Top
EuGen Администратор
Отправлено: 10 Декабря, 2011 - 10:28:33
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Не путайте union и join

http://mysql[dot]ru/docs/man/UNION[dot]html


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
unambigos
Отправлено: 10 Декабря, 2011 - 11:38:34
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




EuGen, нет, это помоему не то, вот инфа с Хабра, кторая меня и заставила засомневаться

Цитата:
взяв на вооружение простое правило — «никогда не выполнять запросы в цикле». Примеры того, как это можно сделать:

1. Выборки
$news_ids = get_list('SELECT news_id FROM today_news ');
while($news_id = get_next($news_ids))
$news[] = get_row('SELECT title, body FROM news WHERE news_id = '. $news_id);

Правило очень простое — чем меньше запросов, тем лучше (хотя из этого, как и из любого правила, есть исключения). Не забывайте про конструкцию IN(). Приведенный код можно написать одним запросом:
SELECT title, body FROM today_news INNER JOIN news USING(news_id)


Только вот беда, пример приведен, а я понять ничего не могу и нигде нормальной информации нет, которая могла бы мне помочь понять это.
 
 Top
EuGen Администратор
Отправлено: 10 Декабря, 2011 - 14:25:43
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




unambigos пишет:
Только не для объединения разных таблиц, а для выборки из одной.

По-другому это сложно понять.
Сформулируйте точно, что Вам нужно. Почитайте отдельно про join и union - поймете разницу.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
unambigos
Отправлено: 11 Декабря, 2011 - 11:45:38
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




EuGen, прочитал, немного вкурил, но не пойму как объединения таблиц могут мне помочь, таблица у меня одна. Мне необходимо избавиться от запросов к базе в цикле. Это при величине каталога в 300 позиций всего например 30 позиций 1-го уровня и по 10 позиций 2-го на каждый из 30, будет 40 запросов к базе при загрузке каталога. А если позиций намного больше? Вот и надо придумать как обойтись несколькими нестандартными запросами вне цикла. Вчера пробовал добавить поле уровня вложенности. Двумя запросами создал 2 массива с пунктами 1 уровня и с пунктами 2 уровня. И с помощью 2х циклов и условия вывести их. Но ничего не получилось. Позже выложу код, может я что нибудь не так делаю?
 
 Top
tuareg
Отправлено: 11 Декабря, 2011 - 12:08:52
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Я так понял Вам надо вывести дерево каталогов. На форуме поищите есть темы.
А так выдергивайте всю таблицу в массив и сортируйте его как Вам надо
 
 Top
unambigos
Отправлено: 11 Декабря, 2011 - 17:54:46
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




Вот код, который призван работать с массивами для вывода каталога. НО он не работает, скажите где ошибка?

Должен выводить, и выводит код который представлен в шапке темы:

ПУНКТ 1 ПУНКТ 2
пункт1.1 пункт2.1
пункт1.2 пункт2.2
пункт1.3 пункт2.3

А вот код, который ниже выводит только:

ПУНКТ 1 ПУНКТ 3
пункт1.1
пункт1.2 ПУНКТ 4
пункт1.3

ПУНКТ 2

Не пойму в чем проблема, чисто логически все должно работать((



CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. <?php
  3.  
  4. @mysql_connect("localhost","12345","12345") or die("Ошибка подключения к базе MySQL!");
  5. @mysql_select_db("example") or die("Ошибка подключения к базе данных");
  6.  
  7. @$res = mysql_query("SELECT id,name FROM catalog WHERE parent=0");//выборка пунктов 0 уровня вложенности
  8. @$myarray = mysql_fetch_row($res);  
  9.  
  10. @$res2 = mysql_query("SELECT id,name,parent FROM catalog WHERE inv='1'");//выборка пунктов 1 уровня вложенности
  11. $num = mysql_num_rows($res2);//подчсчет количества
  12. @$myarray2 = mysql_fetch_array($res2);
  13.  
  14. $cols = 2;
  15. $str = ceil($num/$cols);
  16. $j = 0;
  17.  
  18. for($i=0;$i<=$cols;$i++)
  19. {
  20.    $content = "<div class='column'>";
  21.        while($myarray = mysql_fetch_array($res) AND $j<=$str)//вывод пунктов 0 уровня вложенности
  22.        {
  23.            $content.="<h3>".$myarray['name']."</h3><ul>";
  24.                while($myarray2 = mysql_fetch_array($res2))//вывод пунктов 1 уровня вложенности
  25.                {  
  26.                    if($myarray['id']==$myarray2['parent'])
  27.                    {
  28.                        $content.="<li>".$myarray2['name']."</li>";
  29.                        $j++;      
  30.                   }
  31.                }  
  32.            $content.="</ul>";
  33.        }    
  34.    $content.="</div>";
  35.    if($str<$num)$str+=ceil($num/$cols);    
  36.    echo $content;  
  37. }
  38. ?>
 
 Top
unambigos
Отправлено: 13 Декабря, 2011 - 11:00:52
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




Почему никто не хочет мне помочь Огорчение Почему код предыдущего поста выводит такую охинею?
 
 Top
Panoptik
Отправлено: 13 Декабря, 2011 - 11:11:56
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011  
Откуда: Одесса, Украина


Помог: 131 раз(а)




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


-----
Just do it
 
 Top
unambigos
Отправлено: 13 Декабря, 2011 - 14:19:03
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




Panoptik

Есть таблица category в базе под названием example

Она имеет следующий вид
id/name/parent
1/Телефоны/0
2/Ноутбуки/0
3/Компьютеры/0
4/LG/1
5/Nokia/1
6/HP/2
и т.д

где поле parent имеет значение id родителя, находящеголся в этой же таблице

Требуется вывести данные из базы данных (каталог, дерево каталогов кому как нравится) в произвольное число колонок, ну например в 3 колонки. Чтобы сначала шли заголовки <h3>Родитель с parent=0</h3> <ul><li>Список детей</li></ul>. Результат приблизительно отображено на сайте slando.ru.
 
 Top
Panoptik
Отправлено: 13 Декабря, 2011 - 15:12:13
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011  
Откуда: Одесса, Украина


Помог: 131 раз(а)




я часто применяю подобные функции при построении меню, хотя предпочитаю пользоваться дивами, а не списками, но логика всё равно остается та же:
PHP:
скопировать код в буфер обмена
  1.  
  2. function get_tree($parent,$level) {
  3.   $level++;
  4.   $query = "SELECT * FROM `category` WHERE `parent` = ".$parent;
  5.   $result = mysql_query($query);
  6.   if(mysql_num_rows($result)) {
  7.     print "<ul>";
  8.     while($row = mysql_fetch_assoc($result)) {
  9.       print "<li>";
  10.       print "<h".$level.">".$row['name']."</h".$level.">";
  11.       //здесь можно всунуть проверку на то есть ли в данной категории дочерние элементы. но в данном случае я обойдусь грубо без проверки, просто выведу пустые теги если никого нет
  12.       get_tree($row['id'],$level);
  13.       print "</li>";
  14.     }
  15.     print "</ul>";
  16.   }
  17. }
  18.  
  19. //вызов функции в таком виде:
  20. get_tree(0,0);
  21.  


писал на колене, так что не судите строго

(Отредактировано автором: 13 Декабря, 2011 - 15:14:37)



-----
Just do it
 
 Top
unambigos
Отправлено: 13 Декабря, 2011 - 17:53:25
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




Panoptik Спасибо большое, все работает, я в восторге!!! Только не пойму, зачем нужна переменная $level?


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

(Отредактировано автором: 13 Декабря, 2011 - 18:08:49)

 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Работа с СУБД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB