|
|
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Задача: нужно вывести продукты по выбранным свойствам. Такое наверное встречали на каждом сайте, где присутствует фильтр. Таблицы: 1) Продукты - собственно сами продукты. Код: sql 1. 2. 3. 4. 5. 2) Имена свойств(к примеру "тип", "диагональ", "формат экрана"). Код: sql 1. 2. 3. 4. 5. 3) Значения свойств(к примеру "жк-телевизор", "22", "16:9" соответственно). `ff_id` - связка с test_feature_fields.ff_id Код: sql 1. 2. 3. 4. 5. 6. 4) Сопоставления продуктов с парами свойство - значение свойства p_id - связка с test_products.p_id ff_id - связка с test_feature_fields.ff_id fv_id - связка с test_feature_values.fv_id Код: sql 1. 2. 3. 4. 5. 6. INSERT: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. В данном примере допустим я выбираю продукт, у которого тип=знач1 и цвет=знач3 и должен вывести "товар1". Много чего перепробовал, пробовал даже INTERSECT, который, прогуглив, нашёл у вас на форуме. Долго с ним мучался, а потом прочитал вверху форума SQLite :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 05:51:36 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
ExOLiNe, 1. Вставки (пакет ваших инсертов) - в боевом применении надо заворачивать в транзакцию. Это раз. Особенно, если учесть, что "юзверь" часто один - апач. 2. Посмотрите поиском в направлении EAV. Уже есть мноо примеров КАК выбирать и по одному и по набору параметров. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 06:39:10 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
ExOLiNe, Сдуреешь от такой криптографии. Зачем вы сами себе жизнь портите? Без русского: CREATE TABLE `product` ( `id` int(11) NOT NULL AUTO_INCREMENT, `val_id` int(11) NOT NULL default 1, `product_name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `product_key` ( `id` int(11) NOT NULL AUTO_INCREMENT, `key_name` varchar(255) NOT NULL, PRIMARY KEY(`id`) ); CREATE TABLE `product_val` ( `id` int(11) NOT NULL AUTO_INCREMENT, `key_name_id` int(11) NOT NULL, `val_name` varchar(255) NOT NULL, PRIMARY KEY(`id`) ); SELECT * FROM product, product_key, product_val where product_val.id = product.val_id AND product_key.id = product_val.key_name_id AND product.id = $something; Не тестил, теоретически все должно получиться, потому что схема каноничная. Получите кучу лишних полей, естественно, поскольку *. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 10:12:12 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Особенно впечатлил мост `pf_id` int(11) NOT NULL AUTO_INCREMENT, `p_id` int(11) NOT NULL, `ff_id` int(11) NOT NULL, `fv_id` int(11) NOT NULL Юстас Алексу: fftd, tder, desf, psss, psfd, sjsf .... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 10:13:33 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Вы потеряете время на расшифровке в стопицот раз больше чем сэкономите на набивке кода. Я понимаю у многих с клавой нет дружбы, я и сам печатаю тремя с половиной пальцами, но опыт говорит что лучше назвать поле Наименование_Категории и Код_Наименования_Категории чем полчаса скрипеть мозгами и листать структуру чтобы найти n_cat или nm_cat_id ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 10:16:29 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
debloggerCREATE TABLE `product` ( `id` int(11) NOT NULL AUTO_INCREMENT, `val_id` int(11) NOT NULL default 1, `product_name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `product_key` ( `id` int(11) NOT NULL AUTO_INCREMENT, `key_name` varchar(255) NOT NULL, PRIMARY KEY(`id`) ); CREATE TABLE `product_val` ( `id` int(11) NOT NULL AUTO_INCREMENT, `key_name_id` int(11) NOT NULL, `val_name` varchar(255) NOT NULL, PRIMARY KEY(`id`) ); Данный способ мне не подходит, так как values - конкретные значения, которые должны храниться в базе данных. Иначе мне придется на сайте в фильтре либо самому эти значения вручную вставлять для каждого свойства, либо выбирать из product_val distinct-ом `val_name`, что я считаю не есть хорошо. debloggerОсобенно впечатлил мост `pf_id` int(11) NOT NULL AUTO_INCREMENT, `p_id` int(11) NOT NULL, `ff_id` int(11) NOT NULL, `fv_id` int(11) NOT NULL Простите, я на самом деле немного подругому называю, просто хотел сократить названия полей, думал они будут интуитивно понятны, так как являются абревиатурами от F eature_ f ields(ff), F eature_ v alues(fv). debloggerВы потеряете время на расшифровке в стопицот раз больше чем сэкономите на набивке кода. Незнаю, я очень быстро привык, ну не все как я конечно.. debloggerЯ понимаю у многих с клавой нет дружбы, я и сам печатаю тремя с половиной пальцами, но опыт говорит что лучше назвать поле Наименование_Категории и Код_Наименования_Категории чем полчаса скрипеть мозгами и листать структуру чтобы найти n_cat или nm_cat_id Не, я слепой печатник :) Arhat109ExOLiNe, 1. Вставки (пакет ваших инсертов) - в боевом применении надо заворачивать в транзакцию. Это раз. Особенно, если учесть, что "юзверь" часто один - апач. 2. Посмотрите поиском в направлении EAV. Уже есть мноо примеров КАК выбирать и по одному и по набору параметров. 1. Учту, просто я до этого никогда не использовал транзакции. 2. Посмотрел. Сплошь везде только "альтернативы EAV", как будто этот способ самый худший :( Ну буду дальше искать. Однако буду очень рад помощи полезными ссылками, если у кого есть под рукой :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 10:52:32 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
4) Сопоставления продуктов с парами свойство - значение свойства p_id - связка с test_products.p_id ff_id - связка с test_feature_fields.ff_id fv_id - связка с test_feature_values.fv_id CREATE TABLE `test_product_features` ( `pf_id` int(11) NOT NULL AUTO_INCREMENT, `p_id` int(11) NOT NULL, `ff_id` int(11) NOT NULL, `fv_id` int(11) NOT NULL ) AUTO_INCREMENT=1; Два поля лишние, должно быть только `p_id` int(11) NOT NULL, `fv_id` int(11) NOT NULL и они должны быть в PK. ff_id - есть уже в test_feature_values, а суррогатный ключ pf_id просто тут не нужен, он не будет использоваться. Даже если ты оставишь эти поля, тебе нужно ещё добавить UNIQUE CONSTRAINT по продукту и свойству, иначе можно будет создавать несколько значений одного свойства. Хотя ff_id можно и оставить, как раз для такого констрейнта. Вот если бы в test_feature_values не было бы суррогатного ключа, а был бы составной из feature & value_id, можно было бы просто сделать FK на составной PK в test_feature_values. И я не понял, в чём вопрос собственно ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 10:56:25 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Обнаружил один способ, который работает: Код: sql 1. 2. 3. 4. Это для двух свойств. SELECT'ом проходимся и выискиваем поля с одним значением поля, а LEFT JOIN'ом проходимся и находим поля со вторым значением, затем ON pf.`p_id`=pff.`p_id` выбирает только те продукты, у которых есть оба этих свойства. Проблема: Чем больше свойств - тем больше left-join'ов. Если выбранных свойств будет штук 50, то я думаю запрос будет выглядеть не очень красиво, не говоря уже о его производительности при постоянном перепросмотре всей таблицы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 10:57:47 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Транзакции при вставках тут как раз ни на фиг не нужны. Во-первых, не факт, что таблицы вообще транзакционные, а во-вторых, это скрипт инициализации бд, да ещё и тестовый. Не надо там об этом думать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 10:59:01 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
ExOLiNeОбнаружил один способ, который работает: Проблема: Чем больше свойств - тем больше left-join'ов. Если выбранных свойств будет штук 50, то я думаю запрос будет выглядеть не очень красиво, не говоря уже о его производительности при постоянном перепросмотре всей таблицы. Это НЕ проблема. Хоть 200 JOIN-ов. Про производительность поговорим тогда, когда ты покажешь конкретный запрос с конкретным планом и с конкретными тормозами. Ну и надо сказать, некоторые предпосылки такой "плохой производительности" у тебя уже есть в дизайне твоей БД, так что либо переделывай структуру, либо не ной и пиши и оптимизируй запросы. Запрос у тебя не совсем правильный, он должен выбирать продукты , а JOIN-ить каждое свойство. JOIN НЕ МОЖЕТ быть OUTER, поскольку это фильтр по AND. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 11:03:33 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
MasterZiv4) Сопоставления продуктов с парами свойство - значение свойства p_id - связка с test_products.p_id ff_id - связка с test_feature_fields.ff_id fv_id - связка с test_feature_values.fv_id CREATE TABLE `test_product_features` ( `pf_id` int(11) NOT NULL AUTO_INCREMENT, `p_id` int(11) NOT NULL, `ff_id` int(11) NOT NULL, `fv_id` int(11) NOT NULL ) AUTO_INCREMENT=1; Два поля лишние, должно быть только `p_id` int(11) NOT NULL, `fv_id` int(11) NOT NULL и они должны быть в PK. ff_id - есть уже в test_feature_values, а суррогатный ключ pf_id просто тут не нужен, он не будет использоваться. Даже если ты оставишь эти поля, тебе нужно ещё добавить UNIQUE CONSTRAINT по продукту и свойству, иначе можно будет создавать несколько значений одного свойства. Хотя ff_id можно и оставить, как раз для такого констрейнта. Вот если бы в test_feature_values не было бы суррогатного ключа, а был бы составной из feature & value_id, можно было бы просто сделать FK на составной PK в test_feature_values. И я не понял, в чём вопрос собственно ? Нет, я просто не стал сюда писать что у меня составной ключ на (p_id, ff_id), я посчитал это не нужным. Суррогатный ключ уберу, ок. Просто привык уже к каждой таблице привязывать авто_инкремент, плохая привычка. Вопрос собственно: как составить оптимальный запрос на выборку продуктов с неограниченным количеством выбранных свойств? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 11:11:09 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
так? Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 11:54:55 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Cygapb-007так? Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. Нет. При выборе пары(ff_id-fv_id) 1-2, 2-3 выводит два товара, хотя должен вернуть NULL ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 12:16:10 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
гуглить "фасетный поиск" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 12:19:01 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Вроде бы нашел решение: Код: sql 1. 2. 3. 4. 5. 6. Производится поиск по таблице-связке всех возможных совпадений через ИЛИ. Потом полученные строки группируются по p_id и подсчитывается количество p_id из результата. Если count(p_id) равен количеству запрашиваемых из базы свойств - значит у продукта есть все запрашиваемые свойства. Но это конечно только подзапрос, но самый важный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 12:19:04 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
ExOLiNeДанный способ мне не подходит, так как values - конкретные значения, которые должны храниться в базе данных. Иначе мне придется на сайте в фильтре либо самому эти значения вручную вставлять для каждого свойства, либо выбирать из product_val distinct-ом `val_name`, что я считаю не есть хорошо. Ваш клиент не умеет редактировать рекордсеты или вы о чем вообще пишите? Сделайте своего клиента который разберется в матерях-дочках или как там, в InnoDB fk профтыкайте ради integrity. Даже VIEW's можно сделать редактируемым, а тут понимаешь полтора справочника и уже проблемы. Все что хранится в базе имеет конкретные значения если база нормальная. Если ненормальная, то зачем база, для этого есть екзель. Короче при чем тут дистинкт и все такое я не понял. Вы можете сделать так чтобы когда основная табля загрузилась в одминку, все связанные справочники выкатились бы списками. Можно и инлайн сделать, но проще на странице редактирования/добавления записи. По-моему это обыкновенно уже давно. Тогда вам ничего ручками вводить не придется, а самая мякотка в том, что в сущности у вас всегда одна таблица с записями которой можно делать что хочешь. Это для отчетов требуются сложные взаимосвязи, а для оперативного управления все должно быть простым как карандаш, иначе оно грохнется от самого управления не дожидаясь пользования. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:21:00 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
И еще, следите за смыслом. Неотъемлимые свойства "отъемлять" не надо. Особенно когда они один фиг - числа. За каким выносить диагонали, диаметры и длину члена в справочник? Я понимаю, чтобы тетка не вписала 17 км, в поле где должно быть 17 дюймов. Но знаете дело в чем - вы все равно не сможете сделать так, чтобы тетка не вписала Поносоник. Кто-то же когда-то же должен завести такую запись в справочнике. Правильно? Если этот кто-то идиот - никакой самый расчудесный клиент ему не поможет. Ну, если только есть некая мировая БД по телеящикам откуда можно взять правЕльное наименование... Это древняя проблема культуры ведения БД в целом, а наша проблема в том что мы теряем грамотность катастрофически. Вот именно, вам можно дать несусветные имена полям - как вы их будете тетке показывать? через шаблон, да? - а тетку хотите избавить от ошибок, которые в легком и понятном клиенте исправить легко и просто. Короче это неколебимо. Одни борются с другими, а в целом все вместе идут ко дну. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:29:02 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
debloggerВаш клиент не умеет редактировать рекордсеты или вы о чем вообще пишите? Как раз таки о том и речь, чтобы клиент мог свободно добавлять/удалять/редактировать values, чтобы они потом по всему сайту где это требуется выпадали списком. А когда значения хранятся как просто строковые, без привязки id - мне кажется тогда уж можно вобще всё упростить до одного текстового поля description, а фильтр тогда сделать просто LIKE '%что-то%' debloggerСделайте своего клиента который разберется в матерях-дочках или как там, в InnoDB fk профтыкайте ради integrity. Даже VIEW's можно сделать редактируемым, а тут понимаешь полтора справочника и уже проблемы. Про VIEW почитаю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:29:22 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Знаете как проектируется идеальная БД и идеальный клиент? Вот так: Внес оператор повторую запись - штраф 1000 р Внес оператор запись с идиоткой ошибкой - штраф 3000 р Через неделю база будет сиять. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:30:19 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Да, конечно, придется сперва платить хорошо. А у нас же все наоборот. Надо набрать идиотов за копейки, которых и штрафовать смысла нет - у него получка на три ошибки. Ну и потом ищутся такие специалисты которые могут сделать идиото-устойчивую БД с клиентом. Получается же все равно гавно. Потому что начальные условия таковы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:32:07 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
[quot ExOLiNe]debloggerА когда значения хранятся как просто строковые, без привязки id А, понятно, без своей криптографии вы уже не понимаете написанное человеческим языком. У меня не было таких полей - все справочники связаны через identity с таблей товаров. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:35:21 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
Или не увидев священных иннер джойнов вы даже и смотреть в табли не стали? :) Ну, да, а как же без них. Ну сделайте на явных джойнах. Нужны нулы - на лефтах. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:36:20 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
ExOLiNeНет. При выборе пары(ff_id-fv_id) 1-2, 2-3 выводит два товара, хотя должен вернуть NULLгы... Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 13:52:13 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
ExOLiNeВопрос собственно: как составить оптимальный запрос на выборку продуктов с неограниченным количеством выбранных свойств? Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 16:18:30 |
|
||
|
Выборка продуктов по свойствам
|
|||
|---|---|---|---|
|
#18+
ExOLiNeВроде бы нашел решение: Код: sql 1. 2. 3. 4. 5. 6. Производится поиск по таблице-связке всех возможных совпадений через ИЛИ. Потом полученные строки группируются по p_id и подсчитывается количество p_id из результата. Если count(p_id) равен количеству запрашиваемых из базы свойств - значит у продукта есть все запрашиваемые свойства. Но это конечно только подзапрос, но самый важный. Это неверный ответ. В смысле, запрос. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.07.2013, 16:20:41 |
|
||
|
|

start [/forum/topic.php?fid=47&msg=38350487&tid=1836345]: |
0ms |
get settings: |
7ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
38ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
75ms |
get tp. blocked users: |
1ms |
| others: | 215ms |
| total: | 371ms |

| 0 / 0 |
