Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Оптимизация выборки из трех таблиц, Найти оптимальный алгоритм 
:(
    Опции темы
KonstRuctor
Дата 4.2.2012, 23:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Есть стандартный вывод новостей.
Таблица news:
Код
id | date | title | text

У каждой новости может быть один или несколько авторов.
Таблица authors:
Код
id | name | email

Таблица "кто что написал": news_authors
Код
news_id | author_id

Мне нужно получить стандартный вывод новостей в виде:
------------------------------------------------------------
1 января 2012 :: Вася Пупкин, Мария Коловынова
Залоговок новости
Текст новости текст новости
------------------------------------------------------------
31 декабря 2011 и так далее
* * *
Сейчас я делаю так:
1) Выборка всех новостей
Код

$q = mysql_query("SELECT * FROM news ORDER BY date DESC");

2) Для каждой новости по ее id вынимаю массив с именами авторов, то есть внутри цикла обхода новостей делаю по запросу для каждой новости
Код

while ( $data = mysql_fetch_assoc($q) )
{
создаю массив $authors для $data['id']
и далее опять же в цикле его вывожу на экран, так как автор может быть не один
}

В итоге для 10 новостей мне надо сделать 11 запросов. Все работает, но не оптимально.
Вопрос: можно ли эту задачу решить одним запросом, получив единый массив всех новостей уже со всеми авторами?
Спасибо.
PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 5.2.2012, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 2
Всего: 71



Что-то где-то так
Код

SELECT a.id AS id_news, a.date, a.title, a.text, b.id AS id_author, b.name, b.email
FROM news AS a
LEFT JOIN news_authors AS c ON c.news_id = a.id
LEFT JOIN authors AS b ON b.id = c.author_id




--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
KonstRuctor
Дата 5.2.2012, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Сделал по вашему примеру.
Вот ято я делал:
Код

$q = $db->query("SELECT a.id AS id_news, a.date, a.title, a.text, b.id AS id_author, b.name, b.email
FROM news AS a
LEFT JOIN news_authors AS c ON c.news_id = a.id
LEFT JOIN authors AS b ON b.id = c.author_id") or die (mysql_error());

$data = $db->fetch_assoc($q);

echo "<pre>";
print_r ($data);
echo "</pre>";

Вот что я получил на выходе:
Код

Array
(
    [id_news] => 1
    [date] => 2012-02-01 11:57:27
    [title] => Первая главна новость в списке
    [text] => текст первой новости
    [id_author] => 2
    [name] => Мария Афанасьевна Колыванова
    [email] => [email protected]
)

В таблице 5 ностей, 5 авторов, таблица news_authors тоже заполнена каким-то образом.
Я получаю только одну новость.
Как мне получить массив с перечнем всех новостей, со всеми авторами к каждой новости?
Или я чо-то делаю не так?
Спасибо!

Это сообщение отредактировал(а) KonstRuctor - 5.2.2012, 11:29

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  test.sql 2,54 Kb
PM MAIL WWW ICQ   Вверх
ksnk
Дата 5.2.2012, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 14
Всего: 386



Цитата(KonstRuctor @  5.2.2012,  11:17 Найти цитируемый пост)
Или я чо-то делаю не так?

Обычно fetch_assoc делается в цикле  smile 


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
KonstRuctor
Дата 5.2.2012, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Как правильно сделать, чтобы сработал 1 запрос?

Это сообщение отредактировал(а) KonstRuctor - 5.2.2012, 11:51
PM MAIL WWW ICQ   Вверх
ksnk
Дата 5.2.2012, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 14
Всего: 386



У меня это запрос вывел 8 строк. C каждым автором... Так и надо?

Добавлено через 1 минуту и 5 секунд
Цитата(KonstRuctor @  5.2.2012,  11:50 Найти цитируемый пост)
Как правильно сделать, чтобы сработал 1 зарос?

Что такое $db - класс из Pear?


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
KonstRuctor
Дата 5.2.2012, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Мне надо на выходе получить перечень новостей (всего их 5)
Для каждой новости надо получить их авторов и вывети на экран.
Я понимаю, что я что-то не так делаю, но никак не могу понять, что....
PM MAIL WWW ICQ   Вверх
Gold Dragon
Дата 5.2.2012, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 2
Всего: 71



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


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
KonstRuctor
Дата 5.2.2012, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Вот что я хочу получить в идеале:
1) Испольщуем мою базу
2) Делаем запрос (здесь $db->query === mysql_query)
Код

$q = $db->query("SELECT * FROM news");
while ( $data = $db->fetch_assoc($q) )
{
    echo "<h2>".$data['title']."</h2>\n";
    echo "<p>".$data['date']." :: ";

    $q1 = $db->query("SELECT a.name FROM authors a, news_authors n WHERE n.author_id = a.id AND n.news_id = '".$data['id']."'");
    while ( $row = $db->fetch_assoc($q1) )
    {
        echo $row['name'].", ";
    }
    echo "</p>\n";
    echo "<p>".$data['text']."</p>\n";
    echo "<hr>\n";
}

И получаем на выходе HTML вывод новостей
Код

<h2>Первая главная новость в списке</h2>
<p>2012-02-01 11:57:27 :: Мария Афанасьевна Колыванова, Катя, </p>
<p>текст первой новости</p>
<hr>
<h2>Вторая гравная новость в списке</h2>
<p>2012-02-02 11:57:48 :: Вася Пупкин, </p>
<p>текст второй новоси</p>
<hr>
<h2>Третья главная новость в списке</h2>
<p>2012-02-03 11:58:20 :: Мария Афанасьевна Колыванова, Катя, </p>
<p>текст третьей новости</p>
<hr>
<h2>Четвертая новость</h2>
<p>2012-02-04 11:58:33 :: Вася Пупкин, </p>
<p>текст четвертой новости</p>
<hr>
<h2>Пятая новость в списке</h2>
<p>2012-02-05 11:58:47 :: Вова, Катя, </p>
<p>текст пятой новости</p>
<hr>

Таким образом я мог решить зедачу.
Вопрос: можно ли сделать это 1 запросом, получив некий масив и, разобрав его, получить вот такой HTML?
PM MAIL WWW ICQ   Вверх
$дмитрий
Дата 5.2.2012, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1037
Регистрация: 19.6.2004

Репутация: 3
Всего: 45



Цитата

В итоге для 10 новостей мне надо сделать 11 запросов. Все работает, но не оптимально.

Нужно всего 2 запроса:
1. Единый запрос news_authors+authors, с последующим формированием массива вида
$arAuthor['ID новости'] = array('Первый автор', 'Второй автор' ...);
2. Список всех новостей news

При выводе новостей, по ID-новости, брать авторов из массива $arAuthor



PM MAIL   Вверх
KonstRuctor
Дата 5.2.2012, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Мне это нужно для построения новостей с пагинатором.
Класс пагинатора принимает один запрос.
Если бы автор у каждой новости был 1, я решил бы задачу легко.
Сейчас я кидаю в пагинатор простой запрос, строю вывод новостей без авторов,
а потом во Вью опять обращаюсь к базе в цикле foreach.
Это во-первых противоречит концепции MVC, к тому же соверщенно не оптимально. 
PM MAIL WWW ICQ   Вверх
ksnk
Дата 5.2.2012, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 14
Всего: 386



KonstRuctor, Уже предложен запрос. Gold Dragon, его предложил. Это запрос выводит все новости, считая, что у каждой новости по 1-му автору. В итоге получается не 5, а 8 новостей в массиве.
При выводе списка новостей достаточно запоминать, что новость с таким ID уже была выведена и дополнять новость с таким ID информацией о новом авторе.




--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
KonstRuctor
Дата 5.2.2012, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Прошу прощения, я не понял этот алгоритм. Не понимаю, как это сдедать.
PM MAIL WWW ICQ   Вверх
ksnk
Дата 5.2.2012, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 14
Всего: 386



2 прохода.
Сначала собираем массив новостей + дописываем к ним авторов.
Потом сбрасываем все новости с готовым списком авторов с html.
Код


$news=array();

$q = $db->query("...");
while ( $data = $db->fetch_assoc($q) )
{
    if(!isset( $news[$data['id_news']])){
        $news[$data['id_news']]=$data;
    }
    $news[$data['id_news']]['authors'][]=$data;
}

foreach($news as $data)
    echo "<h2>".$data['title']."</h2>\n";
    echo "<p>".$data['date']." :: ";
    foreach($data['authors'] as $row){
    {
        echo $row['name'].", ";
    }
    echo "</p>\n";
    echo "<p>".$data['text']."</p>\n";
    echo "<hr>\n";
}



Это сообщение отредактировал(а) ksnk - 5.2.2012, 12:47


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
KonstRuctor
Дата 6.2.2012, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 245
Регистрация: 31.3.2006
Где: Россия, Санкт-Пет ербург

Репутация: нет
Всего: нет



Спасибо! Теперь я понял идею работы приложения.
В моем случае, при работае с пагинатором, на мой взгляд, такой подход не годится, так как искажается общее кол-во новостей...
Пока я пришел к такому выводу, что буду использовать 11 запросов к базе вместо 1.
CI позволяет вычислить бенчмарк, поэтому я смогу реально увидеть разницу в скорости работы сайта с 1 запросом (без авторов вообще) и с 11 запросами (с авторами, получаемыми в цикле).
О результатах обязательно сообщю. 
Спасибо!!!
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.0600 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.