За последние 24 часа нас посетил 30441 программист и 1809 роботов. Сейчас ищут 844 программиста ...

CrossReference (перекрёстные ссылки) номеров

Тема в разделе "PHP для новичков", создана пользователем graf_vorontsov, 6 фев 2013.

  1. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    Такая задача: есть файл с определёнными номерами деталей, в поле поиска вводится номер детали и ищу этот номер в файле. Но если номер вводимый пользователем отличается от того номера что содержится в файле, то естественно результат выдаст пустой. Но дело в том что запчасти бывают разных фирм и естественно имеют разные номера, пользователь не может знать по какой именно фирме находится у меня в наличии запчасть, поэтому номер может ввести одной фирмы а у меня эта деталь по другой фирме.
    Пример: 4a0407151 аналог 935716 аналог JTC254 ну и т.д. аналогов может быть много.
    На сколько понял это реализуется с помощью перекрёстных ссылок, т.е. какбы один номер равен другому, пользователь вводит любой из этих номеров а ему выдаёт то что есть в наличии.
    Хочу сделать как на http://exist.ua/, я знаю что там большая база номеров выдертая из программы, но мне не нужно столько номеров, мне достаточно их будет в ручную набить в файлик заменители эти.

    1) как правильно составить файлик с аналогами?
    4a0407151;935716;JTC254 - так нормально будет?

    2) как привязать номера между собой?
    4a0407151==935716==JTC254 -?

    3) сам запрос на поиск результата
    strstr($number1, $number2) но с учётом перекрёстных ссылок
    в переменную $number1 получается надо подставлять каждый номер сюда?

    4) или надо в бд заливать кроссы номеров и при выборке сравнивать?

    Вобщем направте меня пожалуйста.
     
  2. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    вот что наваял....
    Код (Text):
    1.         $vhod = "4a0407151";
    2.    
    3.     $crosse0 = "evr15";
    4.     $crosse1 = "15689";
    5.     $crosse2 = "89f6";
    6.     $crosse3 = "4a0407151";
    7.    
    8.     $cross = array($crosse0, $crosse1, $crosse2, $crosse3);
    9.    
    10.     $v_faile = array("evr1","561","89f6","ERV5678");
    11.    
    12.     foreach ($cross as $element){
    13.  
    14.         if($vhod == $cross['0']||$vhod == $cross['1']||$vhod == $cross['2']||$vhod == $cross['3']){
    15.  
    16.             foreach ($v_faile as $file_element){
    17.                 $return = strstr($file_element, $element);
    18.                 echo $return;
    19.             }        
    20.                        
    21.         }
    22.  
    23.     };
    подправте пожалуйста
     
  3. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    подправил чтоб искало вне зависимости от наличия пробелов точек... и.т.д.
    Код (Text):
    1.     $vhod = "4a0.407 151";
    2.        
    3.     $cross = array("evr15", "15689", "89f6", "4a0407151");
    4.    
    5.     $v_faile = array("evr1","561","89kf6","evr15","ERV5678");
    6.    
    7.     function normalize_number($data_corected) {
    8.         return preg_replace("#\W#", "", $data_corected);
    9.     };
    10.     function are_numbers_equal($number1, $number2) {
    11.         return strstr(normalize_number($number1), normalize_number($number2));
    12.     }
    13.    
    14.     foreach ($cross as $element){
    15.  
    16.  
    17.             if(are_numbers_equal($vhod, $cross['0'])
    18.                 ||are_numbers_equal($vhod, $cross['1'])
    19.                 ||are_numbers_equal($vhod, $cross['2'])
    20.                 ||are_numbers_equal($vhod, $cross['3'])){
    21.  
    22.             foreach ($v_faile as $file_element){
    23.  
    24.                 $return = are_numbers_equal($file_element, $element);
    25.                 echo '<pre>';
    26.                 echo $return;
    27.                 echo '</pre>';
    28.             }        
    29.                        
    30.         }
    31.  
    32.     };
    но не ищет если не дописать номер.. например написать не 4a0.407 151 а 4a0 407 15
    я понимаю что получается что программе не с чем сравнивать, но бывают номера которые заканчиваются на 01C или B41 ... и народ не всегда это дописывает.
     
  4. Tokha

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

    С нами с:
    29 янв 2013
    Сообщения:
    77
    Симпатии:
    0
    Если правильно понял, при указании одной детали, надо получить список всех имеющихся аналогов.

    Вникать в код не стал. Слишком сложно для моего времени суток.
    Но по теме могу предложить два варианта:
    1. В файле - каждая строка "номер" детали, если для этой детали существуют аналоги, они все будут записаны в одной строке через определенный разделитель. При поиске просто находим строку с искомым номером, частью номера, результат explode() на найденной строке даст список всех аналогичных деталей.
    2. База данных - Таблица "номера". В ней два поля "номер" и "тип детали". У "деталей - аналогов" тип будет одинаковым. Я далеко не мастер в построении запросов, и сделал бы, для начала, двумя:
    а. Находим деталь с LIKE в условии. (можно при этом и часть номера иметь и полный)
    б. Находим все детали с тем же типом.
    Мне вариант с базой ближе. Он гибче, проще поддается расширению и будет шустрее работать, но вносить данные придется сложнее чем в файл ручками.
     
  5. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    та ничего сложного, файл сделать а потом загрузить его в базу. нормально.

    завтра буду думать над остальной частью
     
  6. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    не понял насчёт полей...
    в каком поле что размещать...
    одному товару может соответствовать до 10 номеров аналогов.. наверное 10 полей надо делать.. или как?
     
  7. Tokha

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

    С нами с:
    29 янв 2013
    Сообщения:
    77
    Симпатии:
    0
    Талица из двух полей:
    Поле 1: Номер, артикул или что там еще детали, например, "12345JPG"
    Поле 2: Тип детали, например 1, или "Фара", или "Бампер от Инфинити", что соответствует числу 523

    Если у нас Бамперы к Инфинити производят 5 разных заводов и у каждого свой артикул, в базе будет 5 записей:
    12346PG => 523
    4321GH => 523
    ЛяЛяЛя => 523
    и т.д.

    В момент поиска, пользователь вводит, например, "321GH".
    результат "SELECT * FROM zapchasti WHERE artikul LIKE %321GH%" даст нам искомую юзером запись.
    Далее, имея тип из предыдущего запроса, "SELECT artikul FROM zapchasti WHERE type = 523" положит Вам на блюде все варианты бамперов к Инфинити, которые у Вас есть.
     
  8. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    ага.. ясно, пробую.....
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Топикстартер пишет про файл, но конечно эту работу удобнее доверить базе. Файл разве что для начальной загрузки справочника использовать.

    Есть код оригинальной детали, а есть аналоги. Мне кажется логичным и эффективным описывать узлы и детали прежде всего в оригинальных обозначениях. У записей про неоригинальные детали делать ссылку на id оригинальной детали. Оригинал ссылается сам на себя. Этот факт можно использовать для выбора "только оригинал".

    Очевидно выбор "все аналоги" это все записи с такой же ссылкой как у выбранной детали.

    Поиск по части названия через LIKE.
     
  10. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    вот как сделал загрузку в бд, но не пойму как сделать не через switch... т.к. строчек в файле может быть около 2тысяч... в ручную писать case 2000: както неочень :))))))))))))
    Код (Text):
    1. foreach ($cross as $key => $elements){
    2.        
    3.         foreach ($elements as $number){
    4.        
    5.         }
    6.                
    7.         switch($key){
    8.            
    9.         case 0:
    10.             $key = 0;
    11.            
    12.             for($i = 0; $i<count($elements);$i++){
    13.            
    14.                 $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')");
    15.  
    16.             }
    17.             break;
    18.         case 1:
    19.             $key = 1;
    20.            
    21.             for($i = 0; $i<count($elements);$i++){
    22.            
    23.                 $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')");
    24.  
    25.             }
    26.             break;
    27.         case 2:
    28.             $key = 2;
    29.            
    30.             for($i = 0; $i<count($elements);$i++){
    31.        
    32.                 $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')");
    33.  
    34.             }
    35.             break;
    36.            
    37.        }  
    38.                        
    39.     };
    нужно чтоб в $key записывалось число соответствующее новой строке...
    что-то не въеду никак как сделать.
    Код (Text):
    1. $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$elements[$i]', '$key')");
    Добавлено спустя 42 минуты:
    но как так сделать? не пойму структуру.. как записи будут выглядеть

    счас вот такого плана получается
    этот массив
    Код (Text):
    1.     $cross = array(
    2.             array("evr15", "15689", "89f6", "4a0407155"),
    3.             array("889656", "3a540987.6"),
    4.             array("1295.12-45", "LMI1845", "rufi2"));
    записывается в базу так
    Код (Text):
    1. number    type_of_number
    2. evr15               0
    3. 15689               0
    4. 89f6                 0
    5. 4a0407155        0
    6. 889656             1
    7. 3a540987.6       1
    8. 1295.12-45       2
    9. LMI1845            2
    10. rufi                  2
     
  11. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    люди подскажите, запутался окончательно

    поиск по базе данных идёт нормально
    Код (Text):
    1.     $return = "89f6";
    2.     $v_faile = array("evr1","561","89kf6","evr15","ERV5678");
    3.    
    4.     foreach($v_faile as $v_faile_num) {
    5.        
    6.         $price = mysql_query ("SELECT * FROM crossnumbers");
    7.         for ($i=0; $i<mysql_num_rows($price); $i++){
    8.             $value = mysql_fetch_assoc($price);
    9.            
    10.             if (are_numbers_equal($value[number], $return)) {
    11.                 //echo $value[number] . '<br>';  
    12.                
    13.  
    14.             }
    15.                
    16.         }
    17.            
    18.            
    19.     }
    20.  
    21.     }
    отбирает значения без проблем
    Код (Text):
    1.            
    2.    
    3.     $pr = mysql_query ("SELECT number FROM crossnumbers WHERE type_of_number = 0");
    4.     for ($j=0; $j<mysql_num_rows($pr); $j++){
    5.         $va = mysql_fetch_assoc($pr);
    6.                    
    7.         echo $va[number] . '<br>';
    но как это связать друг с другом!!???
     
  12. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Я тоже не понял что есть что. foreach (... $key=>...) + switch($key) это откровенный говнокод.
    Давай договоримся что именно мы должны решить:
    * структуру базы или
    * формат файла загрузки или
    * написать скрипт начальной загрузки?
    Предлагаю обсудить эти вопросы отдельно и последовательно.
     
  13. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    1) в бд есть таблица crossnumbers в ней 2 поля number и type_of_number
    2) надо загрузить туда номера деталей с учётом связи между ними.
    делаю так как писал выше... вы сказали что это говнокод :) знаю.. но другое не придумал

    или я даже таблице не такую сделал?......

    3) а скрипт начальной загрузки это вы что имеете ввиду? скрипт который загрузит номера деталей в БД? ну да... я и пытаюсь его правильно сделать, а после надо чтоб ещё и поиск работал.. но до него ещё далеко..
     
  14. Tokha

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

    С нами с:
    29 янв 2013
    Сообщения:
    77
    Симпатии:
    0
    Есть файл, организованный по принципу:
    Строка 1: Номер детали
    Строка 2: Номер детали
    ...
    Строка x: Номер детали,Номер аналога,Номер аналога
    Строка x+1: Номер детали
    ...

    Есть база с двумя полями, у Вас она уже есть.

    Загружаем файл в базу (псевдокод, который можно оптимизировать):
    Код (PHP):
    1. $f = file('имя файла с номерами');
    2. for ($i = 0; $i < count($f); $i++)
    3. {
    4.   $nums = explode($f[i], ',');
    5.   foreach($nums as $num)
    6.   {
    7.     $type = $i + 1;
    8.     mysql_query("INSERT INTO crossnumbers VALUES ('$num', '$type')");
    9.   }
    10. }
    На выходе получаем таблицу с уникальным типом для каждой отдельной детали и одинаковыми для аналогов.
    Поиск заключается в двух элементарных SELECT, приведенных несколькими постами выше.
     
  15. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    ну немножко оптимизировал ваш код :) точнее полность переоптимизировал, но за идею благодарю
    Код (Text):
    1.     $file = fopen("cross.txt", "r");  
    2.    
    3.     function get_array($read_file){
    4.         while(($arr = fgetcsv($read_file, 1000,"\t"))!== FALSE){
    5.         $massiv[] = array_merge($arr);
    6.         }
    7.     return $massiv;
    8.     }
    9.        
    10.     $file = get_array($file);
    11.    
    12.     $i = 0;
    13.  
    14.         foreach ($file as $nums){
    15.            
    16.             $type = ++$i;
    17.  
    18.             foreach($nums as $num){
    19.            
    20.                 $query = mysql_query("INSERT INTO crossnumbers (number, type_of_number) VALUES ('$num', '$type')");
    21.             }
    22.         }
     
  16. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    вот написал выборку исходя из данных введёных пользователем
    Код (Text):
    1.     $user_find = "4D0 898 550";
    2.    
    3.     $zapros = mysql_query("SELECT * FROM `crossnumbers` WHERE `number` LIKE '%$user_find%'");
    4.    
    5.     $row = mysql_fetch_assoc($zapros);
    6.    
    7.     print_r ($row); //выводит найденный результат
    8.    
    9.     $otvet = mysql_query("SELECT `number` FROM `crossnumbers` WHERE type_of_number = '$row[type_of_number]'");
    10.    
    11.     for ($r=0; $r<mysql_num_rows($otvet); $r++){
    12.        
    13.         $roww = mysql_fetch_assoc($otvet);
    14.        
    15.         echo '<pre>';
    16.         print_r ($roww); //выводит отсортированный результат в зависимости от найденного
    17.         echo '<pre>';
    18.     }
     
  17. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    ааа, получилось!! Но есть проблемка: как сравнивать введённый номер пользователя с номерами в БД без учёта символов.. пробелы , точки, запятые, тире и т.д. По части номера ищет хорошо с помощью LIKE, а вот как искать какпопалозаписаное - не знаю :)

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

    Код (Text):
    1. echo '<table border=1>';
    2.    
    3.     $user_find = "622 2400";
    4.    
    5.     $zapros = mysql_query("SELECT * FROM `crossnumbers` WHERE `number` LIKE '%$user_find%'");
    6.    
    7.     $row = mysql_fetch_assoc($zapros);
    8.    
    9.     echo 'Найденый номер в БД'.'<br>';
    10.    
    11.     print_r ($row); //выводит найденый результат
    12.    
    13.     $otvet = mysql_query("SELECT `number` FROM `crossnumbers` WHERE type_of_number = '$row[type_of_number]'");
    14.    
    15.     for ($r=0; $r<mysql_num_rows($otvet); $r++){
    16.        
    17.         $roww = mysql_fetch_assoc($otvet);
    18.        
    19.         echo 'Результат из БД';
    20.        
    21.         echo '<pre>';
    22.         print_r ($roww); //выводит отсортированый результат в зависимости от найденого
    23.         echo '<pre>';
    24.    
    25.         //****************************************
    26.         $file_nalichie = fopen("nalichie.txt", "r");  
    27.    
    28.         $file_nalichie = get_array($file_nalichie);
    29.    
    30.         //echo 'Результат поиска по файлу';
    31.         echo "<tr>";
    32.         foreach($file_nalichie as $nalichie) {
    33.                
    34.             foreach($nalichie as $numero){
    35.                
    36.                 if (are_numbers_equal($numero, $roww['number'])) {
    37.                                  
    38.                     //вывод результата в виде таблицы
    39.  
    40.                     echo "<td style='padding: 6px;'>$nalichie[0]</td><td style='padding: 6px;'>$nalichie[1]</td>"; //если введены данные, выдать найденый результат                                  
    41.                 }
    42.             }
    43.         }
    44.         echo "</tr>";
    45.     }
    46.    
    47.     echo '</table>';
    как мне кажеться.. необходимо чтото дописать тут где LIKE '%$user_find%'
    Код (Text):
    1. "SELECT * FROM `crossnumbers` WHERE `number` LIKE '%$user_find%'"
    есть функция у меня
    Код (Text):
    1.     function normalize_number($data_corected) {
    2.         return preg_replace("#\W#", "", $data_corected);
    3.     };
    4.     function are_numbers_equal($number1, $number2) {
    5.         return strstr(normalize_number($number1), normalize_number($number2));
    6.     }
    с помощью неё я сравниваю уже найденые результаты в БД с номерами в файле

    но не пойму как применить в нужной мне ситуации, т.е. при сравнении то что ввёл пользователь с номерами в БД
     
  18. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    вроде нашёл ответ.. завтра попробую отпишу
    RLIKE ........
     
  19. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    мда... не получается что-то, ХЭЛП!!!
     
  20. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    не делайте так никогда.
    num_rows() - спрашивает у сервера сколько строк в результате. то есть, будет 40 строк - спросит 40 раз, сервер 40 раз пересчитает и вернет цифру 40. если не надо знать только кол-во строк - не используйте num_row()
    fetch_*() - Возвращает ассоциативный массив строк, соответствующий полученному ряду, либо FALSE если рядов больше нет.

    вместо ваших двух строк нужно написать одну
    while( $roww = mysql_fetch_assocc( $otvet ) ){
    итераций будет ровно столько, сколько строк в ответе и без лишней нагрузки на сервер.
    если нужен счетчик - до этой строки объявили (к примеру) i=0 и внутри тела цикла делаем i++

    но это было лирическое отступление. в чем у вас проблема сейчас?
     
  21. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Ganzal, в целом верно, только 40 раз будет считать не сервер, а клиент mysql. На самом деле результат запроса уже ждет нас в буфере. Тем не менее в условии for не надо ставить никаких функций, лучший вариант ты показал.

    Добавлено спустя 3 минуты 23 секунды:
    Я бы в такой ситуации пошел на избыточность - кроме "правильного" номера хранил бы упрощенный без незначащих символов и инкрементальный поиск вел бы именно по такому варианту. Упростил введеную строку - поискал LIKE по упрощенному полю.
     
  22. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    спасибо. принял к сведению! Исправил.

    а проблемка в следующем:
    есть номер хранимый в бд в таком виде - EVR15-121.6
    пользователь вводит в поиск вот такое 151216
    естественно номер не находится
    если введёт так 15-121.6 то ищет нормально
    и если так 15-121

    вот собственно и проблема чтоб поиск работал без учёта символов точки пробелов запятых тире.....а просто сравнивал цифры или буквы номера
     
  23. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    см. выше
     
  24. graf_vorontsov

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

    С нами с:
    12 фев 2011
    Сообщения:
    183
    Симпатии:
    1
    Адрес:
    Украина, Харьков
    та я понял... может есть другой способ :)
    хотя этот тоже вроде ничо....
     
  25. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    только если более сложный в обработке строк.
    хранить избыточно очищенную строку - вполне достаточно.