Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   SQL запрос. Как делать SELECT с условием SELECT (https://javascript.ru/forum/server/39734-sql-zapros-kak-delat-select-s-usloviem-select.html)

Duda.Ml1986@gmail.com 09.07.2013 21:51

SQL запрос. Как делать SELECT с условием SELECT
 
Приветствую.

Есть 3 таблицы.

books хранит данные о книге

user_books хранит данные id из book и id из users, то есть каждый пользователь из users может соответствовать одному или нескольким id из books

users хранит данные о пользователях.

Когда мне нужны книги пользователя из books (тоесть полные данные о книге) я вынужден :

1. Выбрать id пользователя из users т.к. единственная доступная инфа о пользователе: сессия с именем пользователя.

2. Выбрать из user_books все книги пользователям по id пользователя.

3. Выбрать из books данные по книгам по id книг полученные из предыдущего запроса (книг от 1...99 ).

Как можно сделать один такой запрос, например:

Код:

SELECT * FROM `books` WHERE `id`='
SELECT `id_books`FROM `user_books`WHERE `id_user`='
SELECT `id_user`FROM `users` WHERE `user_name`='$_SESSION[''Name']'' '

Естественно что такой запрос не работает, и при том что один из ответов может содержать более одного поля.

МОЖНО ЭТО СДЕЛАТЬ?

П.С. Можно получать id пользователя и в сессии, но тогда все равно остается запрос в запросе.

Буду благодарен за ссылку или пример.
Спасибо.

bes 09.07.2013 22:28

не вникал в то, что ты хочешь, но если хочешь получить конкретное значение при помощи выборки, то запрос (select) должен вернуть ровно одно значение, а сам он помещён в круглые скобки, если же идёт выборка из выборки, то не важно сколько значений вернёт выборка, но она должна быть помещена в круглые скобки

Duda.Ml1986@gmail.com 10.07.2013 00:22

Спасибо за ответы.

Получилось вот что:

SELECT * FROM 
  books b, user_books u, users s
  WHERE
  b.id = u.id_book 
  AND u.id_user = s.id AND
  s.id = 76


Только не совсем ясно как сделать иначе? Потому что:
1. Выбираем все книги которые имеют хозяина
2. из числа выбранных всех изеров которые имеют книги
3. потом оставляем только те книги которые соответсвуют id юзера.

Не слишком ли это затратно, если скажем обьем базы будет 50 мб?
Или всеже так делать норм?

ksa 10.07.2013 09:11

Цитата:

Сообщение от Duda.Ml1986@gmail.com
Когда мне нужны книги пользователя из books (тоесть полные данные о книге)

Как вариант...

select
	*
from
	user_books as ub
    left join books as b on b.id=ub.id_book 
where
	ub.id_user=76

ksa 10.07.2013 09:12

Цитата:

Сообщение от Duda.Ml1986@gmail.com (Сообщение 261431)
Получилось вот что:

SELECT * FROM 
  books b, user_books u, users s
  WHERE
  b.id = u.id_book 
  AND u.id_user = s.id AND
  s.id = 76

Делать декартов куб не продуктивно для решения твоей задачи...

Duda.Ml1986@gmail.com 10.07.2013 19:25

Спасибо.
Ответ гражданина Ksa в 2 раза быстрее чем мой вариант.

bes 10.07.2013 20:59

ksa, зачем внешнее соединение?
если соответствие не поставлено, то и книга не пользователя и пользователь не книги :)

--полные данные о книгах пользователя 76
SELECT * 
FROM books, user_books
WHERE books.id = user_books.id_book AND user_books.id_user = 76

и декартова произведения здесь нет, так как есть ограничивающие условия

ksa 11.07.2013 09:11

Цитата:

Сообщение от bes
и декартова произведения здесь нет

Оно там есть по определению... :D Просто к нему применяется условие.
Т.о. рассматриваются все (!) записи из books и все (!) записи из user_books. После чего к декартову квадрату применяется твое условие.

Соединение же работает несколько иначе...
Из user_books возьмутся только записи удовлетворяющие условию и к ним "присоединиться" запись из books согласно условию соединения.

Т.о. ожидается более быстрый ответ.

Цитата:

Сообщение от bes
если соответствие не поставлено, то и книга не пользователя и пользователь не книги

Это вообще не понял...

bes 11.07.2013 19:20

Цитата:

Сообщение от ksa
Оно там есть по определению... :D Просто к нему применяется условие.
Т.о. рассматриваются все (!) записи из books и все (!) записи из user_books. После чего к декартову квадрату применяется твое условие.

насколько мне известно, более-менее серьёзные субд (такие как от oracle) используют различные внутренние оптимизации для ускорения получения результатов запроса, поэтому описываемый тобой способ реализации запроса на данный момент удобен лишь для освоения sql ;)
предполагаю, что в приведённом мною запросе, это, как минимум, означает, что анализатор, не в последнюю очередь, выполнит второе условие, тем самым уже избавив от декартова произведения

Цитата:

Сообщение от ksa
Это вообще не понял...

я пояснил, что не вижу смысла оставлять лишние записи, которые ты потенциально оставил (если они есть), использовав внешнее соединение

ksa 12.07.2013 11:37

Цитата:

Сообщение от bes
не вижу смысла оставлять лишние записи, которые ты потенциально оставил

Автор использовал мой запрос - лишних записей там нет. :D

Цитата:

Сообщение от bes
описываемый тобой способ реализации запроса на данный момент удобен лишь для освоения sql

Это лишь твое мнение и не более того... :D

ksa 12.07.2013 11:41

Цитата:

Сообщение от bes
насколько мне известно, более-менее серьёзные субд (такие как от oracle) используют различные внутренние оптимизации для ускорения получения результатов запроса

И опять не понятно...
Т.е. декартовы квадраты, кубы и пр. они оптимизировали... А про соединения наверное забыли и они там работают медленнее? :blink:

ksa 12.07.2013 11:43

В любом случае автор может рассказать как отработали наши примеры и выбрать более оптимальный по скорости...

bes 12.07.2013 18:18

Цитата:

Сообщение от ksa
Это лишь твое мнение и не более того... :D

"значимый" аргумент

Цитата:

Сообщение от ksa
Автор использовал мой запрос - лишних записей там нетю :D

в принципе нет смысла в таблице соответствий не ставить соответствий

Цитата:

Сообщение от ksa
Автор использовал мой запрос - лишних записей там нетю :D

так вот в чём причина твоих хи-хи, а я уж было начал подумывать, что у тебя традиция курнуть с утра вместо завтрака :D

Цитата:

Сообщение от ksa
В любом случае автор может рассказать как отработали наши примеры и выбрать более оптимальный по скорости...

вот это по делу

Duda.Ml1986@gmail.com 13.07.2013 14:47

Цитата:

Сообщение от ksa (Сообщение 261880)
В любом случае автор может рассказать как отработали наши примеры и выбрать более оптимальный по скорости...

Код:

select
    *
from
    user_books as ub
    left join books as b on b.id=ub.id_book
where
    ub.id_user=76

0,0018 sec.


Код:

SELECT *
FROM books, user_books
WHERE books.id = user_books.id_book AND user_books.id_user = 76

0.0019 sec.

ksa 15.07.2013 11:04

Цитата:

Сообщение от Duda.Ml1986@gmail.com
0,0018 sec.

Цитата:

Сообщение от Duda.Ml1986@gmail.
0.0019 sec.

Не особо большая разница...

Цитата:

Сообщение от bes
а я уж было начал подумывать, что у тебя традиция курнуть с утра вместо завтрака

Могу только повториться...
Цитата:

Сообщение от ksa
Это лишь твое мнение и не более того...


Veterinar 11.01.2014 23:13

В T-SQL или PL-SQL есть совпадение с неоднозначной выборкой. Может и MySQL так сработает:
SELECT * FROM books
WHERE id in (
SELECT id_books FROM user_books WHERE id_user=(
SELECT id_user FROM users WHERE user_name=$_SESSION[''Name'])
)

kostyanet 13.01.2014 16:09

Вариант без join это join по-ораклу. С декартами они там сами разбираются, нас это николебет. Вариант с join - соответственно ANSI.

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


Часовой пояс GMT +3, время: 11:36.