Помогите сократить запросы.

Тема в разделе "Базы данных", создана пользователем Runapa, 4 ноя 2011.

Модераторы: latteo
  1. Runapa

    Runapa Постоялец

    Регистр.:
    30 окт 2010
    Сообщения:
    63
    Симпатии:
    5
    PHP:
                    //Выводим Список бокового меню
                    
    $sql "SELECT * FROM sub_pages WHERE cat = '$p'";
                    
    $result_cat mysql_query($sql) or die(mysql_error() ."<br/>"$sql);
                    
    //End
        //Выводим текст суб категорий            
        
    $result_sub mysql_query ("SELECT * FROM sub_pages WHERE id = '$p' ORDER BY id"$db);
        
    $sub_row mysql_fetch_array ($result_sub);
        
    $sub_text $sub_row["text_rus"];
        
    //End
    //Выводим список бокового меню на страницах суб категорий
    $sql "SELECT * FROM sub_pages WHERE cat = '$cat'";
    $result_category mysql_query($sql) or die(mysql_error() ."<br/>"$sql);
    //End
    Хотелось бы из этих трёх запросов сделать один. Это реально ? А то не догоняю как. Все данные идут из одной таблицы, а вот используются они по разному.
    Помогите плиз.
     
  2. thoth777

    thoth777

    Регистр.:
    28 ноя 2008
    Сообщения:
    314
    Симпатии:
    98
    немного непонятен этот пассаж: "SELECT * FROM sub_pages WHERE id = '$p' ORDER BY id"
    зачем его сортировать вам было?

    вот что придумалось:

    $sql = "SELECT * FROM sub_pages WHERE cat in('$p','$cat') or id='$p'";
    $res = mysql_query($sql);
    while ($out=mysql_fetch_assoc($res)){
    if ($out['id']==$p){действия}
    if ($out['cat']==$cat){действия}
    if ($out['cat']==$p){действия}
    }
     
  3. malibu

    malibu Создатель

    Регистр.:
    8 июл 2009
    Сообщения:
    20
    Симпатии:
    9
    Все верно, лишь одно небольшое дополнение:
    если есть индексы и по cat и по id, то mysql может сорвать башню и он будет делать полный перебор таблицы. В этом случае лучше сделать через union
    $sql = "SELECT * FROM sub_pages WHERE cat in('$p','$cat') union SELECT * FROM sub_pages WHERE id='$p'";
    Лучше сначала проверить план выполнения запроса с помощью explain.
     
  4. thoth777

    thoth777

    Регистр.:
    28 ноя 2008
    Сообщения:
    314
    Симпатии:
    98
    да не сорвет башню.
    смотрите у ТС в первом посте:
    он в любом случае ищет
    1. WHERE cat = '$p'
    2. WHERE id = '$p'
    3. WHERE cat = '$cat'

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

    explain, union - это дополнительные запросы в базу.
    ИМХО, они не нужны.
     
  5. malibu

    malibu Создатель

    Регистр.:
    8 июл 2009
    Сообщения:
    20
    Симпатии:
    9
    Может я несколько сумбурно просто объяснил, что имел в виду.
    Выборка у ТС изначально идет и по cat и по id. Вы их правильно объеденили в WHERE. Только есть тонкое отличие: у ТС выборки по cat и id идут в РАЗНЫХ запросах. Когда объеденяем эти фильтры в одном запросе, оптимизатор MySql может не понять что от него хотят и начать полный перебор таблицы, вместо использования индексов.

    В случае ТС скорее всего все будет гут, т.к. таблица по идее не должна быть большой, но когда таблица разрастается на 100к+, уже становится заметно.

    По поводу explain, union.

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

    union будет объеденять результаты двух запросов, но когда записей 100к, а результаты работы двух запросов возвращают по пару десятков записей, union будет быстрее, чем перебор 100к записей.

    Вот и все, что я хотел передать в первом посте. А так я сразу написал, что Ваше решение верное, просто решил подкинуть информацию к размышлению.
     
  6. thoth777

    thoth777

    Регистр.:
    28 ноя 2008
    Сообщения:
    314
    Симпатии:
    98
    вы правы

    и не хватает инфы от ТС насчет таблицы - типов данных, как она формируется, сколько там записей и т.п.

    если таблица вырастает до 100к+ записей, уже имеет смысл использовать кэширование.
     
  7. Runapa

    Runapa Постоялец

    Регистр.:
    30 окт 2010
    Сообщения:
    63
    Симпатии:
    5
    Эти запросы отвечают за отображение категорий и субкатегорий на страницах сайта. Там вряд ли когда будет 100к записей. В таблице в основном текстовая информация.

    Вобщем у меня всё получилось как надо. Спасибо.

    Объясните пожалуйста как работает такая конструкция - WHERE cat in('$p','$cat') or id='$p'";. Точнее мне не понятно что делает in.
     
  8. Runapa

    Runapa Постоялец

    Регистр.:
    30 окт 2010
    Сообщения:
    63
    Симпатии:
    5
    PHP:
    or id='$p'";

    if (
    $out['id']==$p){действия}
    эта часть не заработала.
     
  9. thoth777

    thoth777

    Регистр.:
    28 ноя 2008
    Сообщения:
    314
    Симпатии:
    98
    ессно не заработает,
    действия - там должен быть скрипт

    конструкция cat in('$p','$cat')
    срабатывает если значение cat соответствует любому из перечисленных в списке, внашем случае, это '$p' и '$cat'
     
  10. Runapa

    Runapa Постоялец

    Регистр.:
    30 окт 2010
    Сообщения:
    63
    Симпатии:
    5
    про скрипт я в курсе.

    Она вобще не заработала. Делал так

    PHP:
    $sql "SELECT * FROM sub_pages WHERE cat in('$p','$cat')or id='$p'";
    $res mysql_query($sql);
    while (
    $out=mysql_fetch_assoc($res)){
    if (
    $out['id']==$p){
        
    $sub_row mysql_query($sql) or die(mysql_error() ."<br/>"$sql);
            
    $row mysql_fetch_array($sub_row);
                
    $sub_text $row["text_rus"];
                       }
    if (
    $out['cat']==$cat){$result_category mysql_query($sql) or die(mysql_error() ."<br/>"$sql);}
    if (
    $out['cat']==$p){$result_cat mysql_query($sql) or die(mysql_error() ."<br/>"$sql);}
    Выводит в каждой категории не свой текст, а тот у которого id раньше.

    То есть если у страницы есть две подкатегории то в обоих выведет один и тот же текст.
    А надо чтобы разный.

    PHP:
    $sql "SELECT * FROM sub_pages WHERE id = '$p'";
    $sub_row mysql_query($sql) or die(mysql_error() ."<br/>"$sql);
    $row mysql_fetch_array($sub_row);
    $sub_text $row["text_rus"];
    Так работает.