[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Сложный запрос к двум таблицам (убрать дубликаты)
vuler
Добрый день. Работаю с БД очень мало, поэтому возникла одна сложность.
В БД содержится несколько таблиц. основная - users - пользователи, users_contacts - Контакты, ну и по мелочи список город, данные копании
и т.д. Основные - users И users_contacts.
Структура users_contacts - id(номер id юзера в таблице users) - type(тип контакта), value (Значение контакта).
Вот тестовый пример.
id type value
18 phone 33233
18 icq 4212
18 skype 333
18 socset 1112333
19 phone 111
19 icq 333
19 skype 111
19 socset 3333
19 socset 111111
К БД обращаюсь 2-мя запросами. 1) делаю выборку из таблицы users, 2) В цыкле прогоняю всех юзеров и по их id выдираю контакты из 2-й
таблицы.
Если делать один запрос, то узеры будут дублироваться, т.к. записей в таблице users_contacts несколько на одного юзера, а в виде массива
их видимо забрать нельзя.
Вот примеры запросов.
SELECT SQL_CALC_FOUND_ROWS users.id,users.gender,users.login,users.email,users.secondname,users.name,users.thirddname,users.city ,users.date_registr,users.birthday,users.status,users.dolzhnost,users.avatar_link,users.description,c ity_.city_name_ru,region_.region_name_ru,country_.country_name_ru,firms.name firm_name,firms.forma_sob FROM users users LEFT JOIN city_ ON users.city=city_.id LEFT JOIN region_ ON city_.id_region=region_.id LEFT JOIN country_ ON country_.id=city_.id_country LEFT JOIN firms_employ firms_employ ON firms_employ.user_id=users.id LEFT JOIN firms firms ON firms.id=firms_employ.firm_id ORDER BY users.id ASC LIMIT 8, 2
SELECT type,value FROM users_contacts WHERE id='18'
SELECT type,value FROM users_contacts WHERE id='19'
Проблема в том, что когда нужно сделать фильтр по какому-нибудь полю или сделать LIKE из таблицы контактов, последовательность запросов меняется.
т.е. вначале делаем выборку из users_contacts, а потом из users, но если сортировки и LIKE заданы для двух таблиц, то такую выборку сделать уже не возможно.
Итог. Нужен один запрос к БД, но тогда как убрать дубликаты? Можно конечно в цыкле прогонять всю выборку и объединять строчки, но мне
кажется, когда строк станет много - ресурсов это дело сожрет много.
Есть какие-нибудь функции mysql, которые решают подобную проблему?
Заранее спасибо.
walerus
Цитата
но тогда как убрать дубликаты

если в кратце, можно убрать дубли из полученного результата

<?php
$in_array = array( 'тут массив пользователей с первой базы' );

$in_array = array_values( array_unique( $in_array ) );

останутся уникальные ID пользователи.

зы: пишите как то понятнее и размерено по тексту, пользуйтесь предоставленными тегами на форуме, для лучшей читабельности.

Например:
есть таблица "users_contacts", где:
id - номер "id" юзера
type - тип контакта
value - Значение контакта.

строение таблицы:

id | type | value

18 | phone | 33233
18 | icq | 4212
18 | skype | 333
18 | socset | 1112333

19 | phone | 111
19 | icq | 333
19 | skype | 111
19 | socset | 3333

кстати, для чего такая "сложная" таблица, не лучше ли, сделать больше полей, что бы не плодить id юзеров?, по типу, не как у Вас - "id | type | value", а иначе:
id | phone | icq | skype | socset
и вносить уже в них значение, тогда и с дублями проблем не будет.

Valick
vuler, опишите подробнее о каких LIKE идет речь (пример такого условия)



_____________
Стимулятор ~yoomoney - 41001303250491
vital
Цитата
Если делать один запрос, то узеры будут дублироваться,

Дубликаты можно убрать GROUP BY.
Вопрос только в том, что у вас что-то не то в бд, если там есть одинаковые полностью данные.

А делать запросы в цикле в бд - говно дурной тон и вообще волосы выпадут.

_____________
"Нужно быть готовым прислушиваться к тем, кто может тебя чему-нибудь научить. Иначе ты никогда не вырастешь."

Откровенно я никому ниразу не нагрубил. А дать подзатыльник зарвавшемуся юнцу, так это и ему на пользу, и мне в удовольствие. © AllesKlar
vuler
Малец подразобрался.
Запрос записал так..
SELECT SQL_CALC_FOUND_ROWS users.id,users.gender,users.login,users.email,users.secondname,users.name,users.thirddname,users.city ,users.date_registr,users.birthday,users.status,users.dolzhnost,users.avatar_link,users.description,G ROUP_CONCAT(users_contacts.type SEPARATOR '&&&') type,GROUP_CONCAT(users_contacts.value SEPARATOR '&&&') value,city_.city_name_ru,region_.region_name_ru,country_.country_name_ru,firms.name firm_name,firms.forma_sob FROM users users LEFT JOIN city_ ON users.city=city_.id LEFT JOIN region_ ON city_.id_region=region_.id LEFT JOIN country_ ON country_.id=city_.id_country LEFT JOIN users_contacts ON users_contacts.id=users.id LEFT JOIN firms_employ firms_employ ON firms_employ.user_id=users.id LEFT JOIN firms firms ON firms.id=firms_employ.firm_id GROUP BY users.id ORDER BY users.id ASC LIMIT 14, 2

walerus: В таблице users не храню контакты, т.к. их может быть много, а хранить массивы в ячейках не рекомендуется, т.к. телефонов может быть 2 или 3, а постоянно json-ом вгонять и выгонять массивы из ячеек плохая идея.

В данном запросе что я указал в принципе вопрос решается. проблема, а вернее неудобство в следующем. На выходе получаю например.
-["type"]=>
string(37) "phone&&&icq&&&skype&&&socset&&&socset"
["value"]=>
string(17) "1&&&2&&&3&&&4&&&5"
и потом применю доп обработку.

foreach ($this->sql_data as $key=>&$value)
{
$value['type']=explode('&&&',$value['type']);
$value['value']=explode('&&&',$value['value']);
//$temp="";
$i=0;
foreach ($value['type'] as $v){
//echo $v;
$value[$v][]=$value['value'][$i];
$i++;
}
unset($value['type']);
unset($value['value']);
}

Если сделать GROUP_CONCAT(users_contacts.type,users_contacts.value SEPARATOR '&&&')
То он объединит колонки phone1&&&socset3 и т.д. тут постобработка будет сложнее.
vital
Цитата
а хранить массивы в ячейках не рекомендуется, т.к. телефонов может быть 2 или 3, а постоянно json-ом вгонять и выгонять массивы из ячеек плохая идея.

А хорошая идея будет почитать про нормализацию данных, 1-2-3 нормальные формы, и вообще о том как правильно строить бд, что бы не было глупых мыслей пихать в ячейку в бд массив.

_____________
"Нужно быть готовым прислушиваться к тем, кто может тебя чему-нибудь научить. Иначе ты никогда не вырастешь."

Откровенно я никому ниразу не нагрубил. А дать подзатыльник зарвавшемуся юнцу, так это и ему на пользу, и мне в удовольствие. © AllesKlar
bestxp
Цитата (vital @ 27.10.2014 - 18:23)
Цитата
а хранить массивы в ячейках не рекомендуется, т.к. телефонов может быть 2 или 3, а постоянно json-ом вгонять и выгонять массивы из ячеек плохая идея.

А хорошая идея будет почитать про нормализацию данных, 1-2-3 нормальные формы, и вообще о том как правильно строить бд, что бы не было глупых мыслей пихать в ячейку в бд массив.

кроме постгреса) там есть ячейки массивы) где собственно это делать можно и нужно))) для некоторых случаев
vital
Цитата
для некоторых случаев

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

_____________
"Нужно быть готовым прислушиваться к тем, кто может тебя чему-нибудь научить. Иначе ты никогда не вырастешь."

Откровенно я никому ниразу не нагрубил. А дать подзатыльник зарвавшемуся юнцу, так это и ему на пользу, и мне в удовольствие. © AllesKlar
walerus
Цитата
walerus: В таблице users не храню контакты, т.к. их может быть много, а хранить массивы в ячейках не рекомендуется, т.к. телефонов может быть 2 или 3, а постоянно json-ом вгонять и выгонять массивы из ячеек плохая идея.
Вы не так меня поняли, я не просил Вас вгонять массивы в таблицы, я написал про то, что "результато" выборки из таблицы, у вас будет массив, вот с ним и оперировать...

Цитата
SELECT SQL_CALC_FOUND_ROWS users.id,users.gender,users.login,users.email,users.secondname,users.name,users.thirddname,users.city   ,users.date_registr,users.birthday,users.status,users.dolzhnost,users.avatar_link,users.description,G   ROUP_CONCAT(users_contacts.type SEPARATOR '&&&') type,GROUP_CONCAT(users_contacts.value SEPARATOR '&&&') value,city_.city_name_ru,region_.region_name_ru,country_.country_name_ru,firms.name firm_name,firms.forma_sob FROM users users LEFT JOIN city_ ON users.city=city_.id LEFT JOIN region_ ON city_.id_region=region_.id LEFT JOIN country_ ON country_.id=city_.id_country LEFT JOIN users_contacts ON users_contacts.id=users.id LEFT JOIN firms_employ firms_employ ON firms_employ.user_id=users.id LEFT JOIN firms firms ON firms.id=firms_employ.firm_id GROUP BY users.id ORDER BY users.id ASC LIMIT 14, 2
Это тихий ужас а не запрос, для такой "простой" задачи...

КОД БЕРИТЕ В ТЕГИ !!!, для кого они созданы?
killer8080
Цитата (vuler @ 27.10.2014 - 17:21)
В данном запросе что я указал в принципе вопрос решается. проблема, а вернее неудобство в следующем. На выходе получаю например.
-["type"]=>
    string(37) "phone&&&icq&&&skype&&&socset&&&socset"
    ["value"]=>
    string(17) "1&&&2&&&3&&&4&&&5"
и потом применю доп обработку.

foreach ($this->sql_data as $key=>&$value)
  {
  $value['type']=explode('&&&',$value['type']);
  $value['value']=explode('&&&',$value['value']);
  //$temp="";
  $i=0;
  foreach ($value['type'] as $v){
    //echo $v;
    $value[$v][]=$value['value'][$i];
    $i++;
  }
  unset($value['type']);
  unset($value['value']);
  }

всё намного проще user posted image
foreach ($this->sql_data as $row) {
$contacts = array_combine(
explode('&&&', $row['type']),
explode('&&&', $row['value'])
);
...

}
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.