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]   

> Без описания
Specter
Отправлено: 28 Августа, 2014 - 11:57:12
Post Id


Новичок


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


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




Здравствуйте.
Есть 4 таблицы, хочу все необходимые данные получить из одного запроса в бд.
relation_pt - в ней привязки между post_id и tag_id, потому как у posts может быть несколько тегов.
Однако есть небольшая проблема. Поскольку тегов у записи может быть несколько, я бы хотел выдернуть массив этих тегов, т.е. результат получить в таком варианте:
PHP:
скопировать код в буфер обмена
  1.  
  2. 'title' => 'название поста',
  3. 'body' => 'текст поста'
  4. .....
  5. 'tags' => array(
  6.       0 => array(
  7.            id => id
  8.            title => title
  9.            slug => slug
  10.       ),
  11.       1 => array(
  12.            id => id
  13.            title => title
  14.            slug => slug
  15.       ),
  16. )
  17.  

Использую join`ы, однако как можете предположить, в результате получаю один последний тег.

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT `posts`.`id`, `posts`.`title`, `posts`.`pubdate`, `posts`.`body`, `posts`.`comments_num`, `posts`.`cat_id`, `posts`.`slug`, `categories`.`id` AS cat_id, `categories`.`title` AS cat_title, `categories`.`slug` AS cat_slug, `tags`.`id` AS tag_id, `tags`.`title` AS tag_title, `tags`.`slug` AS tag_slug
  2. FROM (`posts`)
  3. LEFT JOIN `categories` ON `posts`.`cat_id` = `categories`.`id`
  4. LEFT JOIN `relation_pt` ON `posts`.`id` = `relation_pt`.`post_id`
  5. LEFT JOIN `tags` ON `relation_pt`.`tag_id` = `tags`.`id`
  6. ORDER BY `pubdate` DESC
  7. LIMIT 10


Вопрос: Есть ли возможность получить результат с массивом тегов? И как?
Мб есть более производительное решение?
Спасибо!
Прикреплено изображение (Нажмите для увеличения)
бд.jpg

(Отредактировано автором: 28 Августа, 2014 - 11:59:32)

 
 Top
Мелкий Супермодератор
Отправлено: 28 Августа, 2014 - 12:05:26
Post Id



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


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


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




Можно, но лучше не надо.
И вам и СУБД будет проще, если теги вытянете отдельным запросом:
сначала посты, собираете id постов, для которых надо достать теги, вторым запросом достаёте теги по этому списку постов.


-----
PostgreSQL DBA
 
 Top
Specter
Отправлено: 28 Августа, 2014 - 12:26:17
Post Id


Новичок


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


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




Спасибо за ответ.
Мелкий пишет:
Можно, но лучше не надо.
И вам и СУБД будет проще, если теги вытянете отдельным запросом:
сначала посты, собираете id постов, для которых надо достать теги, вторым запросом достаёте теги по этому списку постов.

Для всех постов нужно достать теги, но не у всех постов есть теги.
Так много запросов ведь получается, формируем массив из id постов, через where в relation_pt получаем все id тегов, что есть у поста, потом только забираем данные тегов.
Потом результирующий массив нужно будет перебрать и засунуть массив тегов туда.
Не много ли телодвижений? Мне нисколько не проще. Однако
Использую CI, поэтому предпочтительно иметь один большой массив.
Чисто в качестве обучения можете привести запрос, который получает данные за один раз, как описал я в начале темы?

(Отредактировано автором: 28 Августа, 2014 - 12:26:36)

 
 Top
Мелкий Супермодератор
Отправлено: 28 Августа, 2014 - 12:45:24
Post Id



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


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


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




Где много запросов? Два.
PHP:
скопировать код в буфер обмена
  1. $sGetPosts = "select post_id, /**/ from posts /**/";
  2. $rgPosts = array();
  3. foreach ($db->query($sGetPosts) as $rgPost) {
  4.     $rgPost['tags'] = array();
  5.     $rgPosts[ $rgPost['post_id'] ] = $rgPost;
  6.     }
  7.  
  8. if ($rgPosts) {
  9.     $sGetTags = "select post_id, tag_name from tags where post_id in (".join(',',array_keys($rgPosts)).")";
  10.     foreach ($db->query($sGetTags) as $rgTag) {
  11.         $rgPosts[ $rgTag['post_id'] ]['tags'] = $rgTag;
  12.         }
  13.     }

Для вашей структуры таблиц конкретные запросы было писать лениво, но суть должна быть ясна.


-----
PostgreSQL DBA
 
 Top
Specter
Отправлено: 28 Августа, 2014 - 14:43:16
Post Id


Новичок


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


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




А если допустим выводим конкретный пост, делать также 2 запроса?
или "лучше" будет сделать один запрос?
 
 Top
Мелкий Супермодератор
Отправлено: 28 Августа, 2014 - 15:04:56
Post Id



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


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


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




Да, тоже два.
Прочитать по ключу быстрее, чем прочитать по ключу и группировать результат (который из-за текстовых полей группироваться будет на диске)


-----
PostgreSQL DBA
 
 Top
Specter
Отправлено: 28 Августа, 2014 - 15:05:41
Post Id


Новичок


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


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




подытожим(на будущее) :2 foreach + 2 запроса в бд легче и быстрее чем один с кучей джоинов?

(Отредактировано автором: 28 Августа, 2014 - 15:06:27)

 
 Top
Мелкий Супермодератор
Отправлено: 28 Августа, 2014 - 15:14:46
Post Id



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


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


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




Зависит от задачи.


-----
PostgreSQL DBA
 
 Top
Specter
Отправлено: 28 Августа, 2014 - 15:23:43
Post Id


Новичок


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


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




Мелкий пишет:
Где много запросов? Два.
PHP:
скопировать код в буфер обмена
  1. $sGetPosts = "select post_id, /**/ from posts /**/";
  2. $rgPosts = array();
  3. foreach ($db->query($sGetPosts) as $rgPost) {
  4.     $rgPost['tags'] = array();
  5.     $rgPosts[ $rgPost['post_id'] ] = $rgPost;
  6.     }
  7.  
  8. if ($rgPosts) {
  9.     $sGetTags = "select post_id, tag_name from tags where post_id in (".join(',',array_keys($rgPosts)).")";
  10.     foreach ($db->query($sGetTags) as $rgTag) {
  11.         $rgPosts[ $rgTag['post_id'] ]['tags'] = $rgTag;
  12.         }
  13.     }

Для вашей структуры таблиц конкретные запросы было писать лениво, но суть должна быть ясна.

Дык, в два запроса не получится. Потому что нужно будет собрать связи из relation_pt. id постов допустим в переборе массива мы получили, далее нужно получить из relation_pt id тегов. Снова перебрать полученный массив, и только можно будет по id тегов из tags получить данные тегов.
Хм, тут как минимум 3 запроса и 3 цикла. Однако
 
 Top
Sail
Отправлено: 28 Августа, 2014 - 15:48:46
Post Id



Участник


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


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




Specter пишет:
получить из relation_pt id тегов. Снова перебрать полученный массив, и только можно будет по id тегов из tags получить данные тегов

А вот тут-то и надо "join-ить"!
 
 Top
Specter
Отправлено: 28 Августа, 2014 - 16:17:22
Post Id


Новичок


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


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




Sail пишет:
Specter пишет:
получить из relation_pt id тегов. Снова перебрать полученный массив, и только можно будет по id тегов из tags получить данные тегов

А вот тут-то и надо "join-ить"!

Да.
PHP:
скопировать код в буфер обмена
  1. $tags = $this->db->select('relation_pt.post_id, tags.title as tag_title, tags.slug as tag_slug, tags.id as tag_id')
  2.         ->join('tags', 'relation_pt.tag_id = tags.id', 'left')
  3.         ->where_in('post_id', $ids)
  4.         ->from('relation_pt')
  5.         ->get()->result_array();

На выходе массив
PHP:
скопировать код в буфер обмена
  1. Dump => array(3) {
  2.   [0] => array(4) {
  3.     ["post_id"] => string(2) "57"
  4.     ["tag_title"] => string(13) "windows phone"
  5.     ["tag_slug"] => string(13) "windows-phone"
  6.     ["tag_id"] => string(2) "27"
  7.   }
  8.   [1] => array(4) {
  9.     ["post_id"] => string(2) "57"
  10.     ["tag_title"] => string(8) "winphone"
  11.     ["tag_slug"] => string(8) "winphone"
  12.     ["tag_id"] => string(2) "28"
  13.   }
  14.   [2] => array(4) {
  15.     ["post_id"] => string(2) "58"
  16.     ["tag_title"] => string(8) "everbote"
  17.     ["tag_slug"] => string(8) "everbote"
  18.     ["tag_id"] => string(2) "29"
  19.   }
  20. }

Данные постов:
PHP:
скопировать код в буфер обмена
  1.  
  2. [0] => array(9) {
  3.     ["id"] => string(2) "58"
  4.     ["title"] => string(90) "Тайтл 1"
  5.     ["pubdate"] => string(19) "2014-08-27 21:16:49"
  6.     ["body"] => string(2156) "текст"
  7.     ["comments_num"] => string(1) "0"
  8.     ["cat_id"] => string(2) "12"
  9.     ["slug"] => string(17) "everbote-sodatiek"
  10.     ["cat_title"] => string(8) "Категорий 1"
  11.     ["cat_slug"] => string(12) "soft-coll-33"
  12.   }
  13.   [1] => array(9) {
  14.     ["id"] => string(2) "57"
  15.     ["title"] => string(118) "Тайтл2"
  16.     ["pubdate"] => string(19) "2014-08-27 21:15:29"
  17.     ["body"] => string(1320) "Текст"
  18.     ["comments_num"] => string(1) "0"
  19.     ["cat_id"] => string(2) "11"
  20.     ["slug"] => string(15) "win-phome-edlla"
  21.     ["cat_title"] => string(27) "WindowsPhone"
  22.     ["cat_slug"] => string(12) "news-windows"
  23.   }
  24. }
  25.  

Короче очень не удобно получается. И не понятно как засунуть в данные поста данные тегов?
Итого уже два запроса к бд и один цикл.
(Добавление)
Как вариант в результирующем массиве прямо указывать индекс от post_id.

(Отредактировано автором: 28 Августа, 2014 - 16:18:49)

 
 Top
Sail
Отправлено: 29 Августа, 2014 - 12:10:00
Post Id



Участник


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


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




Specter пишет:
И не понятно как засунуть в данные поста данные тегов?

В таблицу relation_pt несколько записей?
На этот случай ведь существует синтаксис:
CODE (SQL):
скопировать код в буфер обмена
  1. INSERT INTO `tablename` (`field1`, `field2`) VALUES ('f1_v1', 'f2_v1'), ('f1_v2', 'f2_v3'), ('f1_v3', 'f2_v3')

***
А если речь о "добыче" информации из массива тегов для определённого поста, то с некоторых пор есть в PHP функция: array_column(), которая может вернуть массив со значениями, взятыми из одной колонки массива и индексами - из другой...

(Отредактировано автором: 29 Августа, 2014 - 12:15:53)

 
 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