Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > LEFT JOIN выборка из многих таблиц


Автор: patap 2.7.2010, 16:49
первый раз столкнулся с такой ситуацией. Стоит использовать такой запрос или лучше получить эти данные несколькими селектами?
пугает возвращаемое кол-во строк примерно 1500. Ну обработать я этот массив смогу, просто хочеться знать как правильно будет
Код

SELECT 
  profile_surname, profile_name, profile_patronymic, profile_birthday, profile_address, profile_registraion, profile_telMobile, profile_telHome, profile_telOther,
  profile_identCode, profile_passportSeries, profile_passportDate, profile_passportOrgan, profile_family, profile_photo, profile_subdivision, profile_startDate, 
  profile_email,
  doc_name, doc_file_name,
  language_type, language_level,
  education_type, education_institute, education_educIn, education_educOut, education_faculty, education_speciality, education_averageScore, 
  education_diplomQuality,
  project_name, project_part, project_duration,
  relative_surname, relative_name, relative_patronymic, relative_birthday, relative_address, relative_relationship, relative_telMobile, relative_telHome, 
  relative_telWork, relative_workPlace, relative_appointment,
  skill_type, skill_name, skill_level, skill_projectAmount, skill_experience,
  unic_name, unic_value
FROM profile
LEFT JOIN document ON profile_id = doc_profile_id
LEFT JOIN language ON language_profile_id = profile_id 
LEFT JOIN education ON education_user_id = profile_id 
LEFT JOIN project ON project_profile_id = profile_id 
LEFT JOIN relative ON relative_profile_id = profile_id 
LEFT JOIN skill ON skill_profile_id = profile_id 
LEFT JOIN unic_field ON unic_profile_id = profile_id 
WHERE profile_id = 1

Автор: ksnk 2.7.2010, 16:53
1500 вариантов? А что с ними делается потом? 
просто выводить на страничку весь список?

Автор: patap 2.7.2010, 17:05
т.к. там LEFT JOIN, то получается по некоторым столбцам дублирование

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

Код

array( // profile - тут будет всего один элемент, т.к. эти данные уникальны для человека
  'profile' => array(
    profile_surname => 'value'
    profile_name =>  'value'
    profile_patronymic =>  'value' 
    ....
  )
  'language' => array(  // language - юзер может иметь много языков
    array(language_type => 'lang val1', language_level => 'lang value1')
    array(language_type => 'lang val2', language_level => 'lang value2')
    array(language_type => 'lang val3', language_level => 'lang value3')
  )
  'education' => array( // education - юзер может иметь много образований
    array(education_type => 'education_type1', education_institute => 'education_institute1', education_educIn => 'education_educIn1')
    array(education_type => 'education_type2', education_institute => 'education_institute2', education_educIn => 'education_educIn2')
    array(education_type => 'education_type3', education_institute => 'education_institute3', education_educIn => 'education_educIn3')
    array(education_type => 'education_type4', education_institute => 'education_institute4', education_educIn => 'education_educIn4')
  )
  ...
  project, relative, skill, unic_field - по анологии с language и education - могут содержать несколько значений
  
)



вот к примеру фрагмент выборки, чтобы было ясно какое дублирование я имею ввиду

[profile_surname]    [profile_name]    [language_type]   [language_level]  [education_type]
  Ivanov                      Ivan                     eng                       6                           height
  Ivanov                      Ivan                     eng                       6                           other
  Ivanov                      Ivan                     eng                       6                           xxxxx
  Ivanov                      Ivan                     ukr                        9                           height
  Ivanov                      Ivan                     ukr                        9                           other
  Ivanov                      Ivan                     ukr                        9                           xxxxx



если обработать эту выборку, то получим массив:

Код

array(
  'profile' => array(profile_surname => 'Ivanov', profile_name => 'Ivan'),

  'language' => array(
     array(language_type => 'eng', language_level => 6),
     array(language_type => 'ukr', language_level => 9)
  ),

  'education' => array(
     array(education_type => 'height'),
     array(education_type => 'other'),
     array(education_type => 'xxxxx'),
  )
)


и далее из этого массива получается компактный вывод инфы на страницу.



Автор: ksnk 2.7.2010, 17:32
Для такого вывода было бы эффективней несколько запросов. Бз join'ов и с  WHERE. imho, объем данных будет меньше, возится с разбором придется меньше. Правда насколько все это добро станет эффективней - надо профилировать...

Автор: patap 2.7.2010, 17:39
ksnk, проект мизерный, никаких больших нагрузок точно не будет.  Я сейчас наверно сделаю по каждой таблице селектом, при данных условиях это большой роли не сыграет, и действительно - не буду возиться с обработкой. 


Просто хотелось бы уяснить на будущее, мало ли где еще встанет такая ситуация - что лучше один запрос или к примеру 8? 


Автор: skyboy 2.7.2010, 22:19
Цитата(patap @  2.7.2010,  16:39 Найти цитируемый пост)
что лучше один запрос или к примеру 8

/*ирония: вкл*/
если каждый из восьми запросов возвращает по 10 записей, никак не связанных друг с другом, то итоговое декартово произведение в 10^8(сто миллионов записей) против 80 при использовании 8 отдельных запросов будет большим выигрышем, да.  smile 
/*ирония: выкл*/
с другой стороны, если из этих 8 таблиц только из первой выбирается 10 записей, а из остальных присоединенных таблиц - максимум по одной на каждую запись из первой таблицы, то в итоге получается те же 80 записей. но их удобней обработать, раз пришло одним запросом.
а по твоему запросу, где в условии связывания(ON ... )  указаны только имена полей без указания таблиц не позволяет даже предположить - к какому случаю относится твой абстрактный вопрос 
Цитата(patap @  2.7.2010,  16:39 Найти цитируемый пост)
что лучше один запрос или к примеру 8? 

так что лучше я отвечу коротко: ДА!

Добавлено @ 22:27
касательно оптимизации запросов рекомендую http://www.ozon.ru/context/detail/id/1895036/
как на меня - отличная книга и с "толстыми", и с тонкими нюансами оптимизации(правда, понял из книги не все, чем похвастаться не могу :( )

Автор: patap 3.7.2010, 23:39
skyboy, ksnk, спасибо за ответы. Информацию проработаю. Думаю, эта тема дала мне толчок в более глубокое изучение SQL))

Автор: Noviy 4.7.2010, 13:43
Меня смущает в этом запросе одно, не выберается информация с таблиц, который джойнятся. Думаю, можно бы было обойтись и без join.
p.s Лучше воспользоваться inner join, ибо нет проверки на null.

Автор: patap 5.7.2010, 09:17
я так понимаю, что явно указывать таблицы нужно если в разных таблицах есть поля с одинаковыми именами, в моем случае таких не имеется, по-этому опустил этот факт.

для проврки все-таки указал табицы явно - результат тот же.
Код

...
LEFT JOIN document ON profile.profile_id = document.doc_profile_id
LEFT JOIN language ON language.language_profile_id = profile.profile_id
...



Автор: skyboy 5.7.2010, 10:20
Цитата(patap @  5.7.2010,  08:17 Найти цитируемый пост)
в моем случае таких не имеется, по-этому опустил этот факт.

дадада. и в перечислении полей и в условиях не указывай имя таблицы, если имя поля уникально.
это:
1. усложнит любую попытку понять, в чем заключается запрос(и тебе тоже - через полгода максимум)
2. приведет к необходимости переписывать все запросы, если внезапно у тебя в двух таблицах появятся одноименные поля

Автор: patap 5.7.2010, 10:35
skyboy, я привык к названию поля подставлять название таблицы, как префикс, поэтому, могу предположить, что второй вариант для меня маловероятен. По первому - согласен, что автоматически устраняет пункт 2 )) 
хотя по пункту 1 - следуя моей логике называния полей, будет не так сложно понять, что к чему.

в общем буду указывать таблицу явно

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)