За последние 24 часа нас посетили 15843 программиста и 1665 роботов. Сейчас ищет 971 программист ...

Вывод связанных записей

Тема в разделе "Прочие вопросы по PHP", создана пользователем Nikolai_, 15 ноя 2013.

  1. Nikolai_

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

    С нами с:
    27 авг 2010
    Сообщения:
    133
    Симпатии:
    0
    Коллеги, подскажите, пожалуйста оптимальное решение. Есть 3 таблицы. В одной географические названия, в другой - номера (номенклатура) карт, в 3-й (связующей) - id названий и карт. В этой 3-й табл. может быть до 5 карт, соответствующих одномук названию. А может быть и нет ни одной записи-связи названия с картой.

    Нужно вывести список названий, а каждому названию - список соответсвующих карт, если есть записи в связ.табл.

    Попробовал выводить названия карт в цикле для каждого названия - см. ниже код ф-ии, которая запускается при выводе каждого названия. Но скрипт начал заметно тормозит уже при 200 записях. Может как-то можно проще решить эту проблему?

    Код (Text):
    1. $query = mysql_query("SELECT tm.id_toponim AS id_toponim, m.id AS id_map, m.name AS map
    2.                       FROM tm tm
    3.                       LEFT JOIN map m ON tm.id_map=m.id
    4.                       ORDER BY m.name ASC;");
    5. while($q = mysql_fetch_array($query)){$maps[] = array('id_toponim' => $q['id_toponim'], 'id_map' => $q['id_map'], 'map' => $q['map']);}
    6. function maps($id){
    7.     global $maps;
    8.     // вывод карт
    9.     $c=0;
    10.     for($i=0; $i<=count($maps); $i++){
    11.         if($maps[$i]['id_toponim'] == $id){
    12.             if($c>0) echo ', ';
    13.             echo $maps[$i]['map'];
    14.             $c++;
    15.         }
    16.     }
    17. }
     
  2. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    Ты что, реально берешь ВСЕ записи, а потом в PHP в цикле выводишь одну из них?

    [​IMG]

    Танцевать надо от SQL запроса. Форматирование данных при выводе это дело двадцатое.
    Что ты хочешь сделать в этом скрипте?
     
  3. Nikolai_

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

    С нами с:
    27 авг 2010
    Сообщения:
    133
    Симпатии:
    0
    От 0 до 5.

    Вывести список названий, а к каждому названию список связанных с ней карт.
     
  4. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    SELECT tm.id_toponim AS id_toponim, m.id AS id_map, m.name AS map
    FROM tm tm
    LEFT JOIN map m ON tm.id_map=m.id
    WHERE tm.id_toponim = :id
    ORDER BY m.name ASC;

    mysql_fetch_array замени на mysql_fetch_assoc и тогда магия с = array(...) просто не нужна, делаешь = $q
    А в цикле убираешь if($maps[$i]['id_toponim'] == $id) т.к. других записей у тебя в принципе не будет.
    Сомнение вызывает и нужность функции c global внутри.

    Добавлено спустя 5 минут 4 секунды:
    Для такой мега задачи, как список значений через запятую, пригодилась бы group_concat. Тогда от скрипта вообще две строки останется :)
     
  5. Nikolai_

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

    С нами с:
    27 авг 2010
    Сообщения:
    133
    Симпатии:
    0
    Так не пойдет. Выведутся лишь карты для одного названия, для которого задан WHERE. А мне нужно для всех. Я вывожу полный список названий с перечнем соответствующих для каждого названия карт.

    Попробую сформулировать задачу еще раз, с начала, на другую тему. Есть таблица title с полями id_doc, name, в которой находятся названия статей. Есть таблица tag с полями id_tag, name, где находятся названия тэгов. Есть таблица связей один ко многому tt с полями id_doc, id_tag - к одному названию статьи может быть много тэгов. Как наиболее оптимально вывести все названия статей и в скобках к каждому названию статьи вывести соотвествующие названия тэгов?
     
  6. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    ошибка: таблица связей многие-ко-многим. один тег может быть у многих статей, одна статья имеет любое количество тегов.

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

    сайт stackoverflow работает именно так.

    Добавлено спустя 7 минут 45 секунд:
    не верю :) ты всегда выводишь все свои 200 названий и все номера карт к ним? и для этого 200 раз вызываешь функию, которая перебирает массив всех, б*ь, карт?
    походу всё еще хуже, чем казалось.

    открой для себя реляционные базы данных.
     
  7. Nikolai_

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

    С нами с:
    27 авг 2010
    Сообщения:
    133
    Симпатии:
    0
    Иначе никак?

    Нужен будет и поиск по тэгам.

    Да, всегда. И записей будет не 200, а около 1000.

    Да, все не очень хорошо. Похоже, стандартная задача, но красивого решения что-то не могу придумать. И ты не очень хорошую вещь предлагаешь. Получается надо будеть забивать сотни раз тэг в виде текста скажем "Северная Америка" вместо ее id скажем в виде цифры 20? Это ведь не рационально. Всего-то разновидностей тэгов будет около 30 и они будут постоянно повторяться.
     
  8. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    хех! если честно, 1000 или 30000 записей это не тот случай, когда что-то может тормозить -- это надо постараться все испортить. настройся позитивно!
    общий совет: не перекладывай манипуляции со множествами на пхп. для этого придуман язык SQL и сервера БД. задача пхп, в-основном, отформатировать вывод.

    Добавлено спустя 26 минут 12 секунд:
    эх, кто бы говорил! ))) зачем ты спрашиваешь совета, если не слушаешь?!
    я качнул себе дамп стековерфлоу за март 2013 для изучения и экспериментов. там записей порядка

    таблица Posts - 13млн
    таблица Tags - 32тыс
    таблица PostTags 14млн

    (а также Users 2млн, Comments 18млн, Votes 38млн и другие)

    так вот, в таблице Posts поле Tags выглядит как "<c><winforms><forms><type-conversion>".
    они пошли на эту избыточность из соображений рациональности. оптимизируются самые частые запросы. на сайте чтение происходит намного чаще, чем запись.
    да, при сохранении сообщения приходится писать теги еще и в текстовое поле. зато когда надо вывести пост, благодаря заложенной избыточности НЕ придется джойнить еще и таблицы PostTags и Tags! (а также НЕ расчитываются всякий раз заново счетчики голосов и НЕ джойнится Users ради никнейма!)

    видишь сколько букв я потратил чтобы показать тебе: есть best practices от очень серьезных разрабов. ты можешь не верить мне, хотя я побольше тебя понимаю, но эти товарищи на пару порядков умнее меня и такая структура отлажена годами.

    Добавлено спустя 19 минут 59 секунд:
    и про group_concat() ты тоже пропустил мимо ушей. а зря!!! с ней ты даже без избыточных полей можешь резко оптимизировать свой список-через-запятую. просто кардинально!
     
  9. smitt

    smitt Старожил

    С нами с:
    3 янв 2012
    Сообщения:
    3.166
    Симпатии:
    65
    А откуда скачать можно?
     
  10. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    http://www.clearbits.net/creators/146-stack-exchange-data-dump
    реально торрент содержит не только stackoverflow, но и другие однотипные проекты этой компании.

    данные в виде xml, как и куда ты заимпортишь дело твоё ;)

    Добавлено спустя 4 минуты 22 секунды:
    в интернетах есть варианты структуры для разных бд. достоверно узнать оригинальную структуру (MS SQL) можно через запросы в "песочнице": http://data.stackexchange.com/stackoverflow/query/new
    EXEC sp_tables
    EXEC sp_help '...'
    и, если мне склероз не изменяет, какие-то мелкие справочники я там же добывал, а не из архива.

    переложение на типы MySQL я делал сам, т.к. всё, что находил было либо фиговым, либо устаревшим - SO модифицируется периодически.
    не проси, не дам ;)
     
  11. Nikolai_

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

    С нами с:
    27 авг 2010
    Сообщения:
    133
    Симпатии:
    0
    Ясно. Так и сделаем. Спасибо, artoodetoo!