|
|
|
| Здравствуйте!
Планирую БД, решил спросить совета.
Есть конфигурационный файл с тремя массивами:
(в каждом массиве до 15 четко определенных элементов)
// Города:
$gorod['1'] = "Город 1";
$gorod['2'] = "Город 2";
$gorod['3'] = "Город 3";
...
$gorod['15'] = "Город 15";
// Род деятельности:
$rd['1'] = "Деятельность 1";
$rd['2'] = "Деятельность 2";
$rd['3'] = "Деятельность 3";
...
$rd['15'] = "Деятельность 15";
// Категории:
$category['1'] = "Категория 1";
$category['2'] = "Категория 2";
$category['3'] = "Категория 3";
...
$category['15'] = "Категория 15";
|
- Это возможные "наборы свойств" компании.
Каждая компания может иметь несколько (3-5-7) свойств из каждого из трех наборов.
Предполагаю примерно следующую таблицу company:
id INT
name TINYTEXT
gorod TINYTEXT
rd TINYTEXT
category TINYTEXT
...
|
В форме добавления записи (компании) в таблицу из массивов формируются наборы чекбоксов (или multiple select -ов).
При формировании запроса INSERT формируются 3 строки, например:
$gorod = ",1,4,12,";
$rd = ",7,8,";
$category = ",3,5,6,15,";
и заносятся в базу (строки с числами, с обоих сторон окруженными запятыми (или любыми другими разделителями)).
Планируются следующие варианты использования:
1 - отображение информации о компании с указанием городов, родов деятельности и категорий, к которым она причастна
Это, полагаю, несложно, и данная реализация хранения в бд (строка с разделителями) оправдана.?
2 - Участие в выборке - например, "вывести все компании, причастные к городу Y, с родом деятельности X" или "вывести все компании категории Z".
Вот здесь я теряюсь в догадках - неужели правильнее/оптимальнее организовать это с помощью пачки дополнительных таблиц (таблицы с массивами свойств плюс связывающие)?
Или использовать LIKE (1 запрос к 1 таблице при любом условии)? | |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 08:57)
| | Намаетесь с такой базой данных, особенно при редактировании. Лично я бы под Города, Род деястельности и Категории выделил бы отдельную таблицу вида
id_city name
1 Город 1
2 Город 2
...
3 Город 3
Плюс еще ввел бы четвертую таблицу (я так понимаю для компаний), которая бы связывала бы Города, Род деятельности и Категории
id name id_city id_rd id_category
Вам базу данных редактировать будет проще и работать она будет на порядок быстрее, так как вы будете оперировать цифрами-связями, а не строками. | |
|
|
|
|
|
|
|
для: cheops
(06.05.2011 в 09:06)
| | Вот спасибо! :-)
Теплилась надежда услышать в ответ "Да, вариант с одной таблицей и LIKE при выборке подойдет".
А если серьезно - пока для меня проще помаяться при редактировании (вывод чекбоксов через foreach из массивов конфига, explode-implode).
А с многотабличной выборкой, да еще и при различных условиях...
Но вопрос я задавал, в первую очередь беспокоясь о производительности.
Отсюда просьба - не направите ли вы ход моих мыслей к дальнеишим действиям?
Уточню условия. Основная таблица - компании. Компания имеет различные поля - имя, адрес и т.д., в числе которых и планировались эти три - город, деятельность и категория, и как раз они предполагаются с множественным выбором.
Теперь таблицу разбиваем на 5:
- компании (ид, имя, адрес, телефон и пр.) - (основная таблица, теперь без полей город, деятельность и категория)
- город (ид, город)
- деятельность (ид, деятельность)
- категория (ид, категория)
- связывающая (ид, компания_ид, город_ид, деятельность_ид, категория_ид)
Так?
Как при этом могут выглядеть запросы:
- на добавление/обновление записи компании с учетом, например, одного города, трех видов деятельности и двух категорий? (понятно, что наборы чекбоксов также несложно сформировать из таблицы)
- отображение нужной компании с указанием города/ов, деятельности/тей, категории/ий к которым она причастна?
- выборка компаний для определенного города, деятельности и категории?
У самого на этот счет только нечленоразборчивая каша в голове. (INSERT INTO компании, связывающая VALUES ... JOIN... ON... ?, SELECT * FROM компании JOIN ...WHERE компании.ид = какиенибудь другие ид из других таблиц...? )
Да, и уточню количество записей в таблицах:
- компании - не более 500 (реально - порядка 200)
- города, деятельности и категории - до 15 | |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 10:09)
| | ну если из таблиц дополнительных параметров компании будут использоваться строго по одному значению, то можно обойтись и без связывающей таблицы - просто поля с айдишниками из доптаблиц добавить в таблицу компаний. | |
|
|
|
|
|
|
|
для: Lotanaen
(06.05.2011 в 10:32)
| | Да, если по одному значению, то проблем нет, но необходим множественный выбор. Например, одна компания может вести деятельность на территории нескольких городов, иметь несколько направлений деятельности и соответствовать нескольким категориям. | |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 10:42)
| | а как много разнообразий в будущем возможно для городов, видов деятельности и т.п. доп данных? т.е. сейчас ваши массивы статичны или динамичны? | |
|
|
|
|
|
|
|
для: Lotanaen
(06.05.2011 в 10:52)
| | Сейчас они статичны и имеют по 8 разнообразий каждый. Ранее я говорил, что их число до 15 (брал с запасом), но в настоящий момент по 8 и изменений не планируется. | |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 11:09)
| | ну если их в будущем никогда не будет более 30, то как вариант могу предложить работать с массивами, а в таблице компаний сделать соответствующие поля типа bigint и в них применить так сказать двоичную систему... т.е. сумму двоек в степенях ключей массивов. тогда никаких доптаблиц не понадобится | |
|
|
|
|
|
|
|
для: Lotanaen
(06.05.2011 в 11:21)
| | Да, думаю что даже более 15 их никогда не будет. Например, города это муниципалитеты некоего района. А как часто в районах тусуются или добавляются/удаляются муниципалитеты? Поэтому эти три "набора свойств" компании - города, деятельность и категория - достаточно статичные и практически неизменные величины, почему я изначально и не планировал заносить их в бд и выделять отдельные таблицы. Если бы их число или названия менялись, то несомненно было-бы логично засунуть их в бд и организовать удобный интерфейс управления. Но ход моих мыслей был таков - засунуть их однажды в конфиг и использовать в режиме чтения, и, возможно, раз в год и придется что-то добавить ручками.
А "сумму двоек в степенях ключей массивов" это как? (если возможно, с примером) И как заносить и выбирать их?
У меня была мысль ключи в двоичной системе, правда в режиме ноль/единица (например, есть 8 городов в списке - имеем 8 активных бит поля "город" в таблице компаний, и если у компании отмечены 3 и 5 города - 3 и 5 бит единицы, остальные нули. Как то так.), а не двоек в степени ключа. Как формировать представляю, а как выбирать - пока нет. Например, как выбрать все компании, у которых 3й бит (или 3й и 5й) в поле "город" - единица. | |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 12:02)
| | ну в принципе тот же двоичный принцип, только не 1 и 0 пишем в таблицу:
вывод формируем примерно так:
foreach ($gorod as $key=>$value) {
if ($town & pow(2,$key)) //$town - значение город из таблицы компаний
echo $value;
}
|
update в таблицу(аналогично и для вставки) :
$arraytown = array (1,3,5);// массив ключей из массива $gorod, которые соответствуют компании
$town=0;
foreach ($gorod as $key=>$value) {
if (in_array($key,$arraytown))
$town+= pow(2,$key);
}
$sql = "update comp set gorod=$town where id=$id";
$res = mysql_query($sql);
|
| |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 12:02)
| | а выборку в таблице аналогично:
$sql = "select * from comp where gorod & ".pow(2,3).">0";
$res = mysql_query($sql);
|
| |
|
|
|
|
|
|
|
для: Lotanaen
(06.05.2011 в 12:47)
| | Большое спасибо за разъяснения.
А как теперь при отображении информации о компании выяснить города, к которым она относится?
И по ходу дискуссии у меня возник вопрос - неужели LIKE так плох? Или просто в данном случае неуместен? | |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 13:01)
| | >А как теперь при отображении информации о компании выяснить города, к которым она относится?
Вот этот код приведенный мною раньше:
foreach ($gorod as $key=>$value) {
if ($town & pow(2,$key)) //$town - значение город из таблицы компаний
echo $value;
}
|
>И по ходу дискуссии у меня возник вопрос - неужели LIKE так плох? Или просто в данном случае неуместен?
like не будет всегда точен (например: Новгород и Нижний Новгород - как правильно выбрать Новгород?) и работает медленее. | |
|
|
|
|
|
|
|
для: Lotanaen
(06.05.2011 в 13:21)
| | Да, но это если "Нижний Новгород", а в моем варианте - цифровые ключи. Причем окруженные с обеих сторон разделителями. В этом случае даже ;Новгород; и ;Нижний Новгород; всегда выберется верно.
Но в любом случае, спасибо. Буду размышлять.
UPD:
И все-равно не пойму.
Например ключи городов у компании - 1, 3
получаем значение в базу - 10 (2+8)
Как теперь достав из базы 10ку вывести города компании (1 и 3) неужели корнями? | |
|
|
|
|
|
|
|
для: exc
(06.05.2011 в 13:31)
| | я же привел выше код вывода списка городов... | |
|
|
|