Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: select (подзапрос возвращает не одно значениие) join-?
 
 автор: root_xxx   (10.11.2014 в 04:23)   письмо автору
 
 

Есть таблица users. Там некоторая инфа о пользователе. ну и понятно что там есть login и ид пользователя (uid).

Еще одна табл frends состоит из uid (обоpначает польpователя из таблицы users), и fuid - это поле тоже ИД пользователя из табл users, но в таблице frends этот столбец идетифицирует друга "столбца uid". И назвал я его fuid.

Таблица имеет следующий вид:

uid fuid dateAdd
--- ---- -----
1    7
1    5
1    12
1    23
5    8
6    4
5    3
3    4
8    10
11    2

---
ДОПИСЫВАЮ: в этой таблице есть еще и третье поле "дата добавления", но это в данном случае не важно.
---

Что это означает. Это значит что у пользователя с ИД 1 есть друзья с ИД 7, 5, 12, 23.

Что нужно: Нужно для пользователя с ИД 1 узнать\выбрать логины его друзей.

В консоли по запросу

mysql> select login from users where uid=(select fuid from frends where uid=1);
ERROR 1242 (21000): Subquery returns more than 1 row
mysql>


это понятно, потому что запрос вернул не одно значение.

Для пользователя с одним другом все работает.


mysql> select login from users where uid=(select fuid from frends where uid=2);
+---------+
| login   |
+---------+
| alex123 |
+---------+
1 row in set (0.00 sec)

mysql>

---
Я еще не учел то что при добавлении друга нужно записать также и другому пользователю этого друга. Подробнее: Например пользователь с ИД 8 добавил себе в друзья пользователя с ИД 100. В бд будет записано что у ИД 8 имеется друг с ИД 100. А пользователю с ИД 100 тоже нужно записать друга с ИД 8.

---
Или писать во второй столбец логин пользователя??? Все равно для составления ссылки (html код на php) нужен будет логин. Только возникнет проблема избыточного хранения инфы и размер бд будет больше чем он должен быть.
---
Может это все неправильно ? как сделать правильнее? Может есть (да конечно есть) примеры алгоритмов? Мне не готовый код нужен а обобщенные алгоритмы, НО где они?

  Ответить  
 
 автор: Trianon   (10.11.2014 в 11:48)   письмо автору
 
   для: root_xxx   (10.11.2014 в 04:23)
 

Вы не могли бы поточнее сформулировать главный вопрос?
для вас, и на данный момент

Потому что на этот поток сознания ответить можно разве что - таки да, join!

  Ответить  
 
 автор: root_xxx   (10.11.2014 в 12:03)   письмо автору
 
   для: Trianon   (10.11.2014 в 11:48)
 

??? Я все детально, НЕкратко :) описал, НО придется еще раз

Есть 1 табл. в ней есть ИД и логин пользователя.

Есть вторая таьбл в ней есть три поля ИД - указывает на ИД в первой таблице и есть поле ФИД - оно тоже указывает на поле ИД с первой тблицы. Третьбе поле второй табл ДАТА - это не столь важно.

Вторая таблица имеет слелдующее содержание

ИД ФИД  дата еще_что_то
1   5  ...
1   2  ...
1   3  ...
6   4  ...
6   7  ...
6   3  ...

Это означает что у пользователя с ИД 1, есть друзья с ИД 5, 2, 3 (во второй табл это поле названо ФИД).

Нужно для пользователя с ИД 1 вывести всех его друзей (вывести логины из ПЕРВОЙ табл, основываясь на ФИД во второй таблице).

  Ответить  
 
 автор: Trianon   (10.11.2014 в 12:12)   письмо автору
 
   для: root_xxx   (10.11.2014 в 12:03)
 

SELECT 
    u.login, u.uid, f.dateadd
  FROM 
    friends f
      JOIN users u  ON f.fuid = u.uid
  WHERE f.uid = 2
  ORDER BY f.dateadd

например

  Ответить  
 
 автор: root_xxx   (10.11.2014 в 12:14)   письмо автору
 
   для: Trianon   (10.11.2014 в 12:12)
 

ага, щас попробую...
---
вау!!! работает, но немного по другому. Щас пример покажу

mysql>
mysql> select uid,login from users;
+-----+---------+
| uid | login   |
+-----+---------+
|   1 | root_x  |
|   2 | xuser   |
|   4 | alex123 |
|   5 | newuser |
+-----+---------+
4 rows in set (0.00 sec)


mysql> select * from frends;
+--------+--------+------------+
| p_fuid | s_fuid | adddate    |
+--------+--------+------------+
|      1 |      2 | 2014-11-10 |
|      1 |      5 | 2014-11-10 |
|      2 |      4 | 2014-11-11 |
+--------+--------+------------+
3 rows in set (0.00 sec)

mysql>


Пришлось переименовать поля uid (из табл users) в p_fuid - primary frend

fuid в s_fuid - secjndary frend

Переименовал потому что была ошибка про то что и в табл users и в табл frends были одинаковые имена стлбцов.

НО весь этот "поток сознания" понятен только мне ;:))

РЕЗУЛЬТАТ такой:

mysql> select uid,login,adddate from users join frends on s_fuid=uid where p_fuid=1;
+-----+---------+------------+
| uid | login   | adddate    |
+-----+---------+------------+
|   2 | xuser   | 2014-11-10 |
|   5 | newuser | 2014-11-10 |
+-----+---------+------------+
2 rows in set (0.00 sec)

mysql> select uid,login,adddate from users join frends on s_fuid=uid where p_fuid=2;
+-----+---------+------------+
| uid | login   | adddate    |
+-----+---------+------------+
|   4 | alex123 | 2014-11-11 |
+-----+---------+------------+
1 row in set (0.00 sec)

mysql>


Вот это и нужно было. НО я вчера и сгеодня ночью перед тем как задать вопрос искал в нете, смотрел в книгу (бумажную!) но так до меня и не дошло. А в тех примерах что я находил все было очень запутано (и даже на этом форуме нечто похожее есть) - но до меня только что дошло!

А щас все понял. И это так просто оказалось.
select uid,login,adddate from users join frends on s_fuid=uid where p_fuid=1;

FROM указывает откуда , а JOIN какбэ связывает таблицы и какбэ создает одну табличку.

И главное ON - сопоставляет поле из одной таблицы с полем во второй. Ну и условие...

  Ответить  
 
 автор: Trianon   (12.11.2014 в 00:43)   письмо автору
 
   для: root_xxx   (10.11.2014 в 12:14)
 

переименовывать поле совсем необязательно было.

В SQL можно (на лету) назначать алиасы(псевдонимы) как таблицам, так и полям.
Для столбцов имя поля можно уточнять именем/алиасом таблицы.
Алиасы имен таблиц ( u для users и f для friends) я показал выше.
Уточнения ( u.login , f.uid ) тоже показал.

Точно также можо было назначить алиас столбику. Например:

SELECT 
    u1.login orig_login, u2.login friend_login, addate
  FROM 
    users u1 
        LEFT JOIN friends f ON f.p_uid = u.uid
        LEFT JOIN users u2 ON u2.uid = f.s_uid
    ORDER BY orig_login, friend_login, addate

  Ответить  
 
 автор: root_xxx   (12.11.2014 в 12:42)   письмо автору
 
   для: Trianon   (12.11.2014 в 00:43)
 

Обращение имя таблицы,.поле_таблицы - в примерах выше не работает.

Щас проверю ваш последний пример...

хм-м... что-то :)) выводит


mysql> SELECT u1.login orig_login, u2.login friend_login, adddate
FROM users  u1
LEFT JOIN frends f ON f.p_fuid = u1.uid
LEFT JOIN users u2 
ON u2.uid = f.s_fuid    
ORDER BY orig_login, friend_login, adddate ;

+------------+--------------+------------+
| orig_login | friend_login | adddate    |
+------------+--------------+------------+
| alex123    | NULL         | NULL       |
| newuser    | alex123      | 2044-10-09 |
| newuser    | root_x       | 2023-08-08 |
| newuser    | xuser        | 2014-11-26 |
| root_x     | alex123      | 2015-10-01 |
| root_x     | newuser      | 2014-11-10 |
| root_x     | xuser        | 2014-11-10 |
| xuser      | alex123      | 2014-11-11 |
| xuser      | newuser      | 2023-10-01 |
| xuser      | root_x       | 2014-10-01 |
+------------+--------------+------------+
10 rows in set (0.01 sec)

mysql>


Та да. Все правильно выводит, НО именно такого вывода не нужно. В алгоритме (в коде) нужно для одного пользователя вывести (или узнать ИД друзей для последующей обработки) всех его друзей.

  Ответить  
 
 автор: Trianon   (12.11.2014 в 13:46)   письмо автору
 
   для: root_xxx   (12.11.2014 в 12:42)
 

Алгоритму - может быть и да.
А Вам?
Впечатление такое, что код из моего ответа Вы увидели, а человеческий текст решили проигнорировать.

>Обращение имя таблицы,.поле_таблицы - в примерах выше не работает.

Запятая откуда?
Точка, а не запятая.

  Ответить  
 
 автор: root_xxx   (12.11.2014 в 14:32)   письмо автору
 
   для: Trianon   (12.11.2014 в 13:46)
 

да там же и точка есть. То просто опечатка.

  Ответить  
 
 автор: Trianon   (12.11.2014 в 14:50)   письмо автору
 
   для: root_xxx   (12.11.2014 в 14:32)
 

так и что не работает?
как раз в отклике mysql видно, что работает

  Ответить  
 
 автор: root_xxx   (12.11.2014 в 14:55)   письмо автору
 
   для: Trianon   (12.11.2014 в 14:50)
 

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

---
А что если писать FROM users AS u1 ? Это же кажись одно и то же, если пишется FROM users u1 - это неявная форма AS ?

  Ответить  
 
 автор: lgar   (04.01.2015 в 17:59)   письмо автору
 
   для: root_xxx   (12.11.2014 в 14:55)
 

AS можно опустить, это одно и тоже.

  Ответить  
 
 автор: Trianon   (04.01.2015 в 21:39)   письмо автору
 
   для: lgar   (04.01.2015 в 17:59)
 

AS желательно опускать - код от этого становится более переносимым.
Насколько мне не изменяет память, в оракле, например, AS писать просто нельзя.

  Ответить  
 
 автор: Лена   (05.01.2015 в 15:52)   письмо автору
 
   для: Trianon   (04.01.2015 в 21:39)
 

>Насколько мне не изменяет память, в оракле, например, AS писать просто нельзя.

Не знаю, как сейчас, но два года назад было можно. В оракле нельзя писать || и & вместо OR и AND, это я точно помню, сама попадалась.

  Ответить  
 
 автор: Valick   (05.01.2015 в 16:06)   письмо автору
 
   для: Лена   (05.01.2015 в 15:52)
 

В оракле нельзя писать || и & вместо OR и AND
А что есть непреодолимое желание??? :D
Мне например и в голову не приходило писать такое в запросах (неважно к какой СУРБД)

  Ответить  
 
 автор: Лена   (05.01.2015 в 16:18)   письмо автору
 
   для: Valick   (05.01.2015 в 16:06)
 

>А что есть непреодолимое желание??? :D
>Мне например и в голову не приходило писать такое в запросах (неважно к какой СУРБД)

Экономия времени :)
Я писала по аналогии с php.

  Ответить  
 
 автор: Trianon   (05.01.2015 в 16:25)   письмо автору
64.8 Кб
 
   для: Лена   (05.01.2015 в 15:52)
 

Я ж это тоже не сам придумал...
В MySQL AS может использоваться как указатель псевдонима поля (в списке SELECT)

SELECT p.id AS pid  ...

а может как указатель псевдонима табличного выражения
  FROM products AS p  JOIN prices AS r ON r.prod = p.id 



Второй вариант применения AS в oracle не проходит.
См приложенную картинку, место я пометил красным.
В первом варианте AS можно опускать.

Вот с тех пор как я это фе увидел, не пишу AS нигде.
Хотя тоже поначалу старался.
Источник

  Ответить  
 
 автор: root_xxx   (05.01.2015 в 22:41)   письмо автору
 
   для: Trianon   (05.01.2015 в 16:25)
 

Я вооюще не использую у себя AS. Потому что надобнности нет. Я изначально хорошо называю таблицы и поля. Обхожусь без AS`ов.

  Ответить  
 
 автор: Valick   (05.01.2015 в 23:15)   письмо автору
 
   для: root_xxx   (05.01.2015 в 22:41)
 

>Потому что надобнности нет.
Просто вы еще не писали запросы при которых без алиасов просто нельзя.

  Ответить  
 
 автор: root_xxx   (10.01.2015 в 18:38)   письмо автору
 
   для: Valick   (05.01.2015 в 23:15)
 

но ведь в программировании как-бэ есть неписанное правило: нужно придерживаться простоты и жизнь будет легче.

  Ответить  
 
 автор: Trianon   (10.01.2015 в 20:06)   письмо автору
 
   для: root_xxx   (10.01.2015 в 18:38)
 

Вот как? Но тогда почему вы используете SQL, а не машину Тьюринга? :)

  Ответить  
 
 автор: root_xxx   (12.11.2014 в 14:58)   письмо автору
 
   для: Trianon   (12.11.2014 в 13:46)
 

>Алгоритму - может быть и да.
>А Вам?

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

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования