[help] Как работает запрос с несколькими таблицами?

Тема в разделе "PHP", создана пользователем HatoL, 17 июл 2008.

Статус темы:
Закрыта.
Модераторы: latteo
  1. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    Пишу скрипт который должен вывести значение поля `text` из таблицы `ranks`. Я недавно начал изучать MySQL, но слышал, что каждый SELECT в запросе отрицательно влияет на производительность, поэтому хотел решить задачу одним запросом (без вложенности). Про то, что в запросе можно каким-то образом связать несколько таблиц я узнал совсем недавно и то, это было только на примере без его разбора. Решил написать сначала несколько запросов, а потом попытаться сделать из них один. Вот решение с несколькими запросами:
    PHP:
        $query_1 mysql_query ('SELECT `player_id` FROM `userlist` WHERE `ggcacc` = ' '\'' RIHL_PLAYER_NAME '\'');
        
    $result_1 mysql_fetch_assoc ($query_1);
        
    $query_2 mysql_query ('SELECT `status` FROM `access` WHERE `player_id` = ' '\'' $result_1['player_id'] . '\'');
        
    $result_2 mysql_fetch_assoc ($query_2);
        
    $query_3 mysql_query ('SELECT `text` FROM `ranks` WHERE `rank_id` = ' '\'' $result_2['status'] . '\'');
        
    $result mysql_fetch_assoc ($query_3);
        return 
    $result['text'];
    Потом, смотря на тот пример, я попытался выполнить эту же задачу одним запросом:
    PHP:
        $result mysql_fetch_assoc(mysql_query('SELECT `ranks`.`text` FROM `userlist` , `access` , `ranks` WHERE
            `userlist`.`ggcacc` = ' 
    '\'' RIHL_PLAYER_NAME '\' AND
            `access`.`player_id` = `userlist`.`player_id` AND
            `ranks`.`rank_id` = `access`.`status`'
    ));
        return 
    $result['text'];
    Но я не понимаю как работает этот запрос! Да, он работает, и даже быстрее чем первый вариант (раза в три), но логику запроса я понять не могу. Например откуда SQL знает, что надо выбирать значение `player_id`, чтобы при этом `ggcacc` было равно тому, что ввел пользователь? Ведь в запросе написано `access`.`player_id` = `userlist`.`player_id`, а намека на то, что на `player_id` надо смотреть, ориентируюясь на значение поля `ggcacc` нигде нет. Сложно все это...
     
  2. Satman85

    Satman85 Создатель

    Регистр.:
    29 ноя 2007
    Сообщения:
    27
    Симпатии:
    3
    Код:
    `userlist` , `access` , `ranks`
    Перечисляя таким образом таблицы, ты производишь декартовое произведение,указанных тобой полей, т.е их всевозможные комбинации,а уже в where задаешь критерий, на основании которого стоит выделить необходимые тебе значения.
    Раз уж ты смотришь в сторону оптимизации,то скажу что такой запрос меделнен намного лучше работает подобные запрос через join
     
    HatoL нравится это.
  3. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    Вроде немного понял, но не совсем... Я так понял, что при таком запросе, как у меня, сервер сначала как бы формирует для себя виртуальную таблицу, которую получает фразой SELECT и перечислением тех полей, которые указаны в исходном запросе в секции SELECT и WHERE. Т.е. в моем примере сервер сначала выполнит такой запрос:
    PHP:
    $query mysql_query('SELECT `userlist`.`ggcacc` , `access`.`player_id` , `ranks`.`rank_id` , `userlist`.`player_id` , `access`.`status` , `ranks`.`text` FROM `userlist` , `access` , `ranks`');
    А потом уже в сгенерированной таблице выполнит мой запрос с той лишь разницей, что в секции FROM будет стоять его как бы "виртуальная" таблица. Так?
     
  4. Miraage

    Miraage Angular/Laravel

    Регистр.:
    3 июн 2008
    Сообщения:
    230
    Симпатии:
    51
    PHP:
    $result mysql_fetch_assoc(
        
    mysql_query('
           SELECT ... UNION SELECT ... UNION SELECT ...
        '
    )
    );
    попробуй так... правда незнаю насколько быстр метод ..
    offtop : RIHL , GGC HM... doter :p
     
  5. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    offtop: угу, помогаю рихл лиге сделать веб-интерфейс для доступа к данным из бота :)

    Использование UNION это все равно что использовать несколько запросов... Ща буду разбираться с JOIN, т.к. ни разу им не пользовался
     
  6. Satman85

    Satman85 Создатель

    Регистр.:
    29 ноя 2007
    Сообщения:
    27
    Симпатии:
    3
    Для простоты если у тебя есть две таблицы (a,b) с одним полем a1,b1 соотвественно, причем таблица a состоит из значений {1,2,3,4,5} , а таблица b {5,6,7,8,9} , то в таком случае при запросе select a1,b1 from a,b будет выведено декартово произведение ,т.е всевозможные комбинации значений полей обеих таблиц всего 30 значений (в данном примере)
    А уже дальше при помощи where ты отбираешь из этого списка то , что тебе нужно.
    Но гораздо лучше присоединять таблицы при помощи join.Так в твоем случае
    запрос
    Код:
    SELECT ranks.text FROM userlist , access , ranks WHERE
            userlist.ggcacc = (твой параметр RIHL_PLAYER_NAME)  AND
            access.player_id = userlist.player_id AND
            ranks.rank_id = access.status
    изменить на

    Код:
    SELECT ranks.text FROM userlist 
    join  access on (access.player_id = userlist.player_id)
    join ranks on (ranks.rank_id = access.status)
    where        userlist.ggcacc = (твой параметр RIHL_PLAYER_NAME) 
    Верную работу не гарантирую,потому как не ясна полная структура связей таблиц в твоей БД
     
  7. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    Второй вариант моего запроса через JOIN работает немного быстрее, чем первый. Проверял следующим циклом:
    PHP:
    for ($i 1$i <= 500$i $i 1)
    {
        
    $query mysql_query ('SELECT `ranks`.`text` FROM `userlist`
            JOIN `access` ON (`access`.`player_id` = `userlist`.`player_id`)
            JOIN `ranks` ON (`ranks`.`rank_id` = `access`.`status`)
            WHERE `userlist`.`ggcacc` = ' 
    rihl_sql_security(RIHL_PLAYER_NAME));
    }
    С другой стороны, не на много. Первый запрос - 2.2-2.3 секунды. Через JOIN - 1.9-2.0.
     
  8. zaartix

    zaartix Постоялец

    Регистр.:
    15 май 2006
    Сообщения:
    73
    Симпатии:
    27
    Не совсем по теме, но пригодится на будущее
    PHP:
    $i=$i+1;
    пишут обычно так
    PHP:
    $i++;
    А вообще довольно много сокращений в пхп, вот примеры:
    PHP:
    $i+=2// $i=$i+2;
    $i $j $n $k// if ($j) {$i=$n;} else {$i=$k;}
     
  9. HatoL

    HatoL

    Регистр.:
    5 фев 2008
    Сообщения:
    206
    Симпатии:
    36
    я это знаю, просто для меня такой код хуже читается ($i = $i + 1 както привычнее :))
     
Статус темы:
Закрыта.