За последние 24 часа нас посетили 18115 программистов и 1699 роботов. Сейчас ищут 1527 программистов ...

Как грамотней построить запрос помогите плиз...

Тема в разделе "PHP и базы данных", создана пользователем Mrak, 1 авг 2006.

  1. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    Есть база на MySql. Задача базы - подобие записной книжки. Есть три таблицы

    Первая таблица - fio. Num - ключевое поле, идентификатор уникального человека в записной книжке, по его значению к конкретной записи привязываются адреса и телефоны, которых может быть несколько для одного человека.

    num fam name otch date
    99 Зайцев Петр Викторович 1984-08-29
    100 Величко Владислав Валентинович 1984-02-28
    101 Денисович Денис Сергеевич 1984-01-01

    вторая таблица - addr. собственно адреса.

    num city street home
    99 Красноярск Металлургов 38
    99 Красноярск Краснодарская 1
    99 Красноярск Урванцева 17
    100 Красноярск Металлургов 51
    101 Красноярск Металлургов 38
    101 Красноярск Краснодарская 1
    101 Москва Аэровокзальная 12

    третья таблица - phone. номера телефонов.

    num tel type
    99 249121 Дом
    99 89232845237 Сот
    100 531498 Дом
    100 89138392872 Сот
    101 531297 Дом
    101 89039888887 Сот

    проблема в том, как грамотней построить запрос. есть форма запроса на php с полем для каждого параметра, которые по сработке формы передаются другому скрипту, который делает запрос в базу. поиск должен осуществляться по любым полям. Например если ввести только телефон - должны выводится все люди с таким телефоном и со всеми данными, которые относятся к каждому из этих людей (адрес, имя, отчество и т.д.). Соответственно, в форме могут оставаться не заполненные поля.

    заранее спасибо за помощь )
     
  2. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    Просьба не говорить, что эту базу можно сделать проще, в одну таблицу. В этом и суть задания, чтобы были три связанные таблицы
     
  3. vasa_c

    vasa_c Активный пользователь

    С нами с:
    22 мар 2006
    Сообщения:
    1.760
    Симпатии:
    0
    Адрес:
    гор.Ленинград
    Мы извращенские задания не решаем. )
     
  4. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    Mrak

    1. пишешь селект который соберет тебе всю инфу одним запросом
    2. навешиваешь туда WHERE
     
  5. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    Первое, что приходит в голову :lol:


    Код (Text):
    1. SELECT f.num, f.fam, f.name, f.otch, f.date, a.city, a.street, a.home, p.tel, p.type FROM `fio` f LEFT JOIN `addr` a ON (a.num=f.num) LEFT JOIN `phone` p ON (f.num=p.num) WHERE [...] GROUP BY f.num;
    Где [...] - это условия LIKE или = для заполненных полей.

    Вот точно - пока пишу это, кто-то уже ответил )
     
  6. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    Селект сразу на три таблицы?
    пишу так
    SELECT * FROM phone, fio, addr WHERE phone.tel='$tel' and fio.name='$nam' and ... и т.д.
    а если одно из условий в форме не было заполнено и переменная, где оно должно было быть пустая. тогда он не находит ничего, т.к. в таблице нету ни одной пустой ячейки. как тогда быть?
     
  7. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    А ты не указывай в SQL запросе пустые ячейки.

    PHP:
    1. <?
    2. $sql=" [...] WHERE ".( $a ? "`a` = '".$a."' AND" : "")." ".( $b ? "`a` = '".$b."' AND" : "")." 1;";
    3. ?>
     
  8. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    а можно подробней про LIKE? ))
     
  9. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    а можно эту строчку разжевать, что значат символы ?, :, . и 1 в конце?
     
  10. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    про LIKE

    можно вместо

    Код (Text):
    1. `pole` = 'значение'
    написать

    Код (Text):
    1. `pole` LIKE '%значение%'
    тогда искаться будет не `pole`, которое равно 'значение', а поле, которое создержит 'значение'.

    % - означает, что там могут быть любые символы.

    А идея была составлять запрос

    "[..] WHERE `pole` LIKE '%".$pole."%'..."

    тогда, если $pole - пустая, будет `pole` LIKE '%%', т.е. любое.

    Но это, ИМХО, глупо. Поэтому смотри ниже.


    про ? : ...
    (условие ? действие_если_условие_верно : действие_если_условие_неверно)

    Если такая конструкция встречается при составлении строки, то вместо нее ставится "действие_если_условие_верно", если условие верно, и "действие_если_условие_неверно" в противном случае.

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

    $sql=" [...] WHERE ". (ЕСЛИ ЕСТЬ $a ТО ДОБАВИТЬ "`a` = '$a' AND")." ".АНАЛОГИЧНО ДЛЯ $b." 1;";

    На конце сформированного запроса будет AND. Чтобы закончить условие, не поменяв его значение, после AND ставим 1.
     
  11. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    Спасибо. уже понятней. только еще бы разобраться и не запутаться где надо ставить " , а где ' .... а расскжажи, поржалуйста, про есть LEFT, что есть JOIN и что есть ON - в доках, которые у меня есть не нашел (
     
  12. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    http://www.mysql.ru/docs/man/JOIN.html

    Текст запроса заключаешь в "

    ` - вокруг названий таблиц и полей
    ' ставишь там, где кавычка должна быть в запросе
    ".()." - там, где ты что-нибудь в запрос вставляешь.

    соответственно
    PHP:
    1. <?
    2. $sql=" [...] WHERE `имя поля` = '".(что-то)."';";
    3. echo $sql;
    4. ?>
    выведет
    Код (Text):
    1. [...] WHERE `имя поля` = 'что-то';

    Но это уже личное дело каждого, как писать :)
     
  13. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    я решил сделать так: глянь плиз где ошибка (не работает):
    (там запрос на поиск по двум полям - имя и телефон)

    Код (Text):
    1. $dan=mysql_query("SELECT * FROM phone, fio, addr
    2. WHERE ".( $tel ? "`phone.tel` = '".$tel."' AND" : "")."
    3. ".( $nam ? "`fio.name` = '".$nam."' AND" : "")." 1;";
    4. GROUP BY fio.num");
    5.  
    6. while($row = mysql_fetch_object($dan)) {
    7.     echo $row->num,"<br>";
    8.     echo $row->nam,"<br>";
    9.     echo $row->tel,"<br>";
    10. }
     
  14. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    PHP:
    1. $dan=mysql_query("SELECT * FROM phone, fio, addr
    2. WHERE ".( $tel ? "`phone.tel` = '".$tel."' AND" : "")."
    3. ".( $nam ? "`fio.name` = '".$nam."' AND" : "")." 1 GROUP BY fio.num");
    4.  
    5. while($row = mysql_fetch_object($dan)) {
    6.     echo $row->num."<br>";
    7.     echo $row->nam."<br>";
    8.     echo $row->tel."<br>";
    9. }
     
  15. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    эхххх. все-равно не работает :(
    вот так работает - но без фильтра на пустые поля:

    Код (Text):
    1. $dan=mysql_query("SELECT * FROM phone, fio, addr WHERE phone.tel='$tel' and fio.name='$nam' GROUP BY fio.num ");
    а так как ты написал - нет :( буду очень благодарен, если отладишь у себя и еще раз проверишь
     
  16. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    смысл в том, что в вышеуказанный запрос добавить фильтр на пустые поля
     
  17. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    А. Точно!

    Если ты пишешь table.field, то ` вокруг имени не нужны.

    PHP:
    1. $dan=mysql_query("SELECT * FROM phone, fio, addr  
    2. WHERE ".( $tel ? "phone.tel = '".$tel."' AND" : "")."  
    3. ".( $nam ? "fio.name = '".$nam."' AND" : "")." 1 GROUP BY fio.num");
    4.  
    5. while($row = mysql_fetch_object($dan)) {  
    6.     echo $row->num."<br>";  
    7.     echo $row->nam."<br>";  
    8.     echo $row->tel."<br>";  
    9. }
     
  18. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    Огромное спасибо. есть же хорошие люди :)
    но только еще одна проблема. вернемся к начальному вопросу - сделать запрос. я делаю так

    Код (Text):
    1. $dan=mysql_query("SELECT * FROM phone, fio, addr
    2. WHERE ".( $nam ? "fio.name = '".$nam."' AND" : "")."
    3. ".( $fam ? "fio.fam = '".$fam."' AND" : "")."
    4. ".( $otch ? "fio.otch = '".$otch."' AND" : "")."
    5. ".( $a1 ? "addr.city = '".$a1."' AND" : "")."
    6. ".( $a2 ? "addr.street = '".$a2."' AND" : "")."
    7. ".( $a3 ? "addr.home = '".$a3."' AND" : "")."
    8. ".( $tel ? "phone.tel = '".$tel."' AND" : "")." 1 GROUP BY fio.num");
    9.  
    10. while($row = mysql_fetch_object($dan)) {
    11. echo $row->num."<br>";
    12. echo $row->name."<br>";
    13. echo $row->fam."<br>";
    14. echo $row->otch."<br>";
    15. echo $row->city."<br>";
    16. echo $row->street."<br>";
    17. echo $row->home."<br>";
    18. echo $row->tel."<br>";
    19. }
    во-первых, он возвращает не тот num, который соответствует человеку
    во-вторых, если ввести только не телефон, то он выводит всех людей в базе и говорит, что у каждого из них такой телефон :(
     
  19. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    А если так?

    PHP:
    1. $dan=mysql_query("SELECT p.*,f.*,a.* FROM phone p LEFT JOIN fio f ON(f.num=p.num) LEFT JOIN addr a ON (a.num=p.num)
    2. WHERE ".( $nam ? "fio.name = '".$nam."' AND" : "")."
    3. ".( $fam ? "fio.fam = '".$fam."' AND" : "")."
    4. ".( $otch ? "fio.otch = '".$otch."' AND" : "")."
    5. ".( $a1 ? "addr.city = '".$a1."' AND" : "")."
    6. ".( $a2 ? "addr.street = '".$a2."' AND" : "")."
    7. ".( $a3 ? "addr.home = '".$a3."' AND" : "")."
    8. ".( $tel ? "phone.tel = '".$tel."' AND" : "")." 1 GROUP BY fio.num");
    9.  
    10. while($row = mysql_fetch_object($dan)) {
    11. echo $row->num."<br>";
    12. echo $row->name."<br>";
    13. echo $row->fam."<br>";
    14. echo $row->otch."<br>";
    15. echo $row->city."<br>";
    16. echo $row->street."<br>";
    17. echo $row->home."<br>";
    18. echo $row->tel."<br>";
    19. }
     
  20. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    а так вообще не работает. может надо обращаться не к table.filed в where, а как-то по-другому?
     
  21. X-Cray

    X-Cray Активный пользователь

    С нами с:
    10 июл 2006
    Сообщения:
    255
    Симпатии:
    0
    Адрес:
    Москва
    $dan=mysql_query("SELECT p.*,f.*,a.* FROM `phone` p LEFT JOIN `fio` f ON(f.num=p.num) LEFT JOIN `addr` a ON (a.num=p.num)
    WHERE ".( $nam ? "f.name = '".$nam."' AND" : "")."
    ".( $fam ? "f.fam = '".$fam."' AND" : "")."
    ".( $otch ? "f.otch = '".$otch."' AND" : "")."
    ".( $a1 ? "a.city = '".$a1."' AND" : "")."
    ".( $a2 ? "a.street = '".$a2."' AND" : "")."
    ".( $a3 ? "a.home = '".$a3."' AND" : "")."
    ".( $tel ? "p.tel = '".$tel."' AND" : "")." 1 GROUP BY f.num");

    while($row = mysql_fetch_object($dan)) {
    echo $row->num."<br>";
    echo $row->name."<br>";
    echo $row->fam."<br>";
    echo $row->otch."<br>";
    echo $row->city."<br>";
    echo $row->street."<br>";
    echo $row->home."<br>";
    echo $row->tel."<br>";
    }

    Изменяя по кусочку (мускул в дауне - иду наощупь, т.ч. если выдает ошибки - говори какие).
     
  22. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    все-равно. не работает.
    ошибки - не могу - пишу из блокнота - проверяю в браузере
    а может упростить задачу - сделать так чтобы возвращало только num записей лиц, которые подходят под критерий.
     
  23. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    Ложная тревога - это я накосячил. все работает. огромнейшее спасибо :)
    вот если бы еще по полочкам разжевал сам селект :)
     
  24. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    именно вот это все:
    Код (Text):
    1. SELECT p.*,f.*,a.* FROM `phone` p LEFT JOIN `fio` f ON(f.num=p.num) LEFT JOIN `addr` a ON (a.num=p.num)
     
  25. Mrak

    Mrak Активный пользователь

    С нами с:
    13 июл 2006
    Сообщения:
    25
    Симпатии:
    0
    и еще вопросик - по датам. работают все сравнения, кроме даты

    Код (Text):
    1. ".( $date ? "f.date = '".$date."' AND" : "")."
    $date получаю так:

    Код (Text):
    1. $day=$_POST["day"];
    2. $mon=$_POST["mon"];
    3. $year=$_POST["year"];
    4. if($year!=""){
    5. $date=$year."-".$mon."-".$day;}