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

Статус
В этой теме нельзя размещать новые ответы.

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` нигде нет. Сложно все это...
 
Например откуда SQL знает надо выбирать значение `player_id`, чтобы при этом `ggcacc` было равно тому, что ввел пользователь? Ведь в запросе написано `access`.`player_id` = `userlist`.`player_id`, а намека на то, что на `player_id` надо смотреть, ориентируюясь на значение поля `ggcacc` нигде нет.
Код:
`userlist` , `access` , `ranks`
Перечисляя таким образом таблицы, ты производишь декартовое произведение,указанных тобой полей, т.е их всевозможные комбинации,а уже в where задаешь критерий, на основании которого стоит выделить необходимые тебе значения.
Раз уж ты смотришь в сторону оптимизации,то скажу что такой запрос меделнен намного лучше работает подобные запрос через Для просмотра ссылки Войди или Зарегистрируйся
 
Вроде немного понял, но не совсем... Я так понял, что при таком запросе, как у меня, сервер сначала как бы формирует для себя виртуальную таблицу, которую получает фразой 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 будет стоять его как бы "виртуальная" таблица. Так?
 
PHP:
$result = mysql_fetch_assoc(
    mysql_query('
       SELECT ... UNION SELECT ... UNION SELECT ...
    ')
);
попробуй так... правда незнаю насколько быстр метод ..
offtop : RIHL , GGC HM... doter :p
 
offtop : RIHL , GGC HM... doter :p
offtop: угу, помогаю рихл лиге сделать веб-интерфейс для доступа к данным из бота :)

Использование UNION это все равно что использовать несколько запросов... Ща буду разбираться с JOIN, т.к. ни разу им не пользовался
 
Для простоты если у тебя есть две таблицы (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)

Верную работу не гарантирую,потому как не ясна полная структура связей таблиц в твоей БД
 
Второй вариант моего запроса через 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.
 
Второй вариант моего запроса через 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.
Не совсем по теме, но пригодится на будущее
PHP:
$i=$i+1;
пишут обычно так
PHP:
$i++;
А вообще довольно много сокращений в пхп, вот примеры:
PHP:
$i+=2; // $i=$i+2;
$i = $j ? $n : $k; // if ($j) {$i=$n;} else {$i=$k;}
 
я это знаю, просто для меня такой код хуже читается ($i = $i + 1 както привычнее :))
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху