Универсальное хранение данных с общими и разными полями

FiW

Новичок
Универсальное хранение данных с общими и разными полями

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

Первым приходит в голову тривиальное решение: в первой таблице (id, date, title, etc, ...) мы храним общие данные, а во второй только те что не совпадают (id, field, data), где id имеет связь один ко многим. Онако данное решение не приемлимо если нам нужны всевозможные выборки данных...

Вторым приходит в голову хранить общие данные в первой таблице, а для других данных создать "вспомогательные" таблицы по "группировке различий". Это приемлимо лишь в том случае, если информация по несоответсвиям нам заранее известна... Наращивать же такое "хранилище" проблематично...

Кто что может предложить по данной теме?

ps: искал по форуму, подобное обсуждали, но "универсального" решения так и не увидел... возможно пропустил - буду рад если ткнут носом :D
 

Фанат

oncle terrible
Команда форума
непонятно, почему нельзя делать "всевозможные выборки данных" в первом варианте
 

FiW

Новичок
Фанат
никто не говорит о том что их нельзя выполнять - нет, просто это быдет ресурсоемко... ну к примеру нужно вынуть за один запрос все товары у которых есть во второй таблице 3 дополнительных поля (ну и про поля в первой таблице не забывай)... как ты себе это представляешь?
 

FiW

Новичок
Автор оригинала: svetasmirnova
>как ты себе это представляешь?
банальный JOIN ?
ключевая фраза - во второй только те что не совпадают (id, field, data), где id имеет связь один ко многим...
т.е. во второй таблице к одной записи может быть несколько записей...
 

svetasmirnova

маленький монстрик
Ну и что? Вот пример с уникальным ключом во второй таблице:
[sql]
select * from table2 join table1 on (table1.id = table2.table1_id) where table2.id = needed;
[/sql]
Если подобной связи нет, то непонятно как ты собрался выбирать нужные записи ресурсоёмким способом.
 

FiW

Новичок
svetasmirnova
Ну для начала я попросил бы Вас быть внимательной, т.к. я писал выше - нужно вынуть за один запрос все товары у которых есть во второй таблице 3 дополнительных поля (ну и про поля в первой таблице не забывай), а приведенный Вами запрос здесь работать не будет... Можете поробывать сами, вот к примеру исходные данные:
[sql]
CREATE TABLE `table1` (
`tid` int(10) unsigned NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
PRIMARY KEY (`tid`)
) TYPE=MyISAM AUTO_INCREMENT=5 ;
INSERT INTO `table1` VALUES (1, 'Товар1');
INSERT INTO `table1` VALUES (2, 'Товар2');
INSERT INTO `table1` VALUES (3, 'Товар3');
INSERT INTO `table1` VALUES (4, 'Товар4');

CREATE TABLE `table2` (
`tid` int(10) unsigned NOT NULL default '0',
`field` varchar(255) NOT NULL default '',
`data` varchar(255) NOT NULL default '',
KEY `tid` (`tid`)
) TYPE=MyISAM;
INSERT INTO `table2` VALUES (2, 'feature1', '...');
INSERT INTO `table2` VALUES (2, 'feature2', '...');
INSERT INTO `table2` VALUES (2, 'feature3', '...');
INSERT INTO `table2` VALUES (4, 'feature1', '...');
INSERT INTO `table2` VALUES (4, 'feature2', '...');
INSERT INTO `table2` VALUES (4, 'feature3', '...');
[/sql]
 

FiW

Новичок
svetasmirnova
нет уж, Вы потрудитесь, будьте так добры... а то смотрю мануал и нечего подобного не вижу. жевать то и не надо - хватить просто самого запроса.

ps: прошу отнестись серьезно (то что я только что зарегался, ни о чем не говорит... просто я здесь очень давно не появлялся)
 

svetasmirnova

маленький монстрик
Да, sorry, FULL JOIN это в Postgres.
Но запрос-то элементарный:
[sql]
SELECT *
FROM table2
JOIN table1 ON table1.tid = table2.tid
where table2.tid = needed
[/sql]
Попробовать лень было?
 

FiW

Новичок
svetasmirnova
Вы издеваетесь? А Вы сами то пробывали? Я ведь писал вверху - ЧИТАЙТЕ ВНИМАТЕЛЬНО! И как минимум проверяйте то, что советуете так уверенно!

ps: Верх упорства - вводить не правильный пароль до тех пор, пока копьютер его не примет.

pss: Я пока думаю, что второй вариант самый приемлимый. Очень жаль, что пока не слышно других предложений (идеологических).
 

alexhemp

Новичок
какая проблема хранить наборы атрибутов неких объектов

нужно всего ничего

1. Справочник типов объектов (type_id, type_name)
2. Справочник типов атрибутов этих объектов (attr_id, type_id, attr_name)
3. Список объектов (object_id, object_type, object_name)
4. Список атрибутов (object_id, attr_id, value).
 

FiW

Новичок
Автор оригинала: alexhemp
какая проблема хранить наборы атрибутов неких объектов

нужно всего ничего

1. Справочник типов объектов (type_id, type_name)
2. Справочник типов атрибутов этих объектов (attr_id, type_id, attr_name)
3. Список объектов (object_id, object_type, object_name)
4. Список атрибутов (object_id, attr_id, value).
Очень схоже с первым вариантом, потому и проблема все та же - каким образом мы отсюда за один запрос вытащим все объекты определенного типа (ес-но включая все аттрибуты которые к ним относятся)?
 

svetasmirnova

маленький монстрик
FiW
Тебе что, нужно вытаскивать только те записи из обоих таблиц, которых ровно 3 с одним tid во второй таблице?
 

alexhemp

Новичок
FiW

Я уже писал как это делать в один запрос даже на mysql 3.x

Поищи топики про хранение каталогов товаров.
Но один запрос - не самоцель - он может работать медленнее чем 2-3 более простых.

-~{}~ 17.09.05 23:32:

А у тебя задача вообще примитивная:

SELECT object_id, object_name, attr_id, attr_value FROM objects INNER JOIN attributes ON (objects.objects_id = attributes.object_id)

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

FiW

Новичок
alexhemp
задача может и примитивная, но как скажите на милость вы получите такой ответ:

id title feature1 feature2 feature3
2 товар2 ... ... ...
4 товар4 ... ... ...

дублирование общих полей не допускается, нужно учитывать что записей в базе много (5-6 нулей), дополнительных полей тоже много (10-20)... примитивная задача )))

то что джойнов может быть куча - это мне известно... вот только когда их будет 20 как это скажется на скорости?

ps: каждый так и норовит сказать "изучайте то, смотрите туда" )))
 

alexhemp

Новичок
FiW

Такой набор от MYSQL вы не получите никогда (в общем случае - когда количество атрибутов заанее неизвестно). Правильный ответ - вам не надо этого хотеть. Хотите такой вывод - напишите простой цикл на PHP, это элементарное условие (пока не изменилась первая колонка - выводим значение, изменилось - перевод строки).

Поверьте - это будет быстрее проще и удобнее, чем извращатся с транспонированием результата.

Такая ф-ция была правда в MS Access - но там это оправдано - сразу такую таблицу пихать автоматически в отчет - ибо среда визуальная.

если количество записей в вашей базе с 5-6 нулями - то прямая дорога - изучать SQL и разделять манипуляции с данными от их представления на экране.

Для вашего варианта - скажите на милость, а как вы названия атрибутов и их идентификаторы будете получать. Где в выборке идентификатор атрибута значение которого выводится в field1?
 

FiW

Новичок
Автор оригинала: alexhemp
Для вашего варианта - скажите на милость, а как вы названия атрибутов и их идентификаторы будете получать. Где в выборке идентификатор атрибута значение которого выводится в field1?
Приведенный мною пример придуманный и максимально упрощенный, главная проблема была как вы догадались в транспонировании!
Автор оригинала: alexhemp
если количество записей в вашей базе с 5-6 нулями - то прямая дорога - изучать SQL и разделять манипуляции с данными от их представления на экране.
Интересные выводы, только я так и не понял что Вы хотели этим сказать... я конечно на гуру по SQL'ю не претендую, но работаю с ним уже далеко не первый год и считаю хорошим тоном (в идеале) все манипулиции с данными проводить в самом SQL'е (уж там для этого предостаточно средств).
Автор оригинала: alexhemp
Такой набор от MYSQL вы не получите никогда (в общем случае - когда количество атрибутов заанее неизвестно). Правильный ответ - вам не надо этого хотеть. Хотите такой вывод - напишите простой цикл на PHP, это элементарное условие (пока не изменилась первая колонка - выводим значение, изменилось - перевод строки).
Поверьте - это будет быстрее проще и удобнее, чем извращатся с транспонированием результата.
Варианты с циклами не подходят ("религия" не позволяет). Да и желание создать такой "контейнер" как раз от того чтобы добиться удобства (ниже поясню)
Ну что ж, посмотрим... вчерашние споры по join'у привели меня к мысли о множественном join'е одной и той же таблицы с разными условиями, т.е.:
были созданы две таблицы
tbl - id, title
tbl_text - id, fid, value - множ.индекс по id и fid; value - типа text
"сборка" проходила так:
[sql]
SELECT t.id, t.title, f1.value f1, ..., f20.value f20
FROM tbl.t
JOIN tbl_text f1 USING(id)
...
JOIN tbl_text f20 USING(id)
WHERE f1.fid=1 AND ... AND f20.fid=20
[/sql]
так же для сравнения я создал другую таблицу
tbl2 - it, title, f1, ..., f20
далее, оба "контейнера" были наполнены данными в количестве 10000 (свойств, как вы догадались 20)
выборка всех строк в простой таблице составляла ~ 1 секунду
в другой же таблице ~ 15-13 секунд (ого! многовато)
мин 15 я искал всевозможные оптимизации, и тут для частоты эксперимента решил сменить тип таблиц с InnoDB на MyISAM.
и о чудо - время "сборки" уменьшилось до ~ 2,3 секунд (вот это уже другое дело). учитывая объемы я склонен считать подобный результат удовлетворительным, пожалуй на этом и остановлюсь :)

Теперь затрону тему зачем. Затем чтобы (к примеру) при появлении нового вида продукции описать только ее класс (модуль), а в нем ее свойства, при этом не создавая никаких дополнительных таблиц.

ps: может у кого то все же будут другие решения?
 

Фанат

oncle terrible
Команда форума
зачем?
ты так вопишь о глупости предложенных тебе вариантов, что нет никакого желания тратить своё время. причём если бы только на написание. потом ведь ещё уговаривать приходится.

читай книжки - они рулез.
 

FiW

Новичок
Фанат
я не говорил о глупости - как оказалось, Светлана меня просто не так поняла (но в icq мы вроде нашли общий язык).

возможно я просто не так объяснил, и не поставил ударение именно на транспонировании...

ps: когда прячешься за книжки, то хотя бы пиши конкретно куда смотреть и что читать, а то так можно на каждый вопрос отвечать :(
 
Сверху