Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: параметрический поиск

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: построение запроса
Zuldek
Отправлено: 05 Марта, 2014 - 09:43:38
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2122
Дата рег-ции: Июнь 2010  


Помог: 50 раз(а)




Доброго времени суток.

items

id | ...


rows

id | id_item | id_row | rows_val


rows - хранит значения дополнительных параметров, id параметра (id_row) и имеет связь один к дному с таблицей items (rows.item_id = items.id)

Есть набор пар id_row и rows_val примеры реальных возможных значений:

id_row = 39 AND rows_val = 70;
id_row = 80 AND rows_val between 70 AND 90;
id_row = 37 AND (rows_val = 1 OR rows_val = 2 OR rows_val >= 4) .

Задача извлечение id из таблицы items, удовлетворяющих этим параметрам поиска (Достаточно извлечение набора id таблицы items без прочих параметров).

Изначально запрос выглядел так (названия полей изменены):

Спойлер (Отобразить)


Естественно, мускул не показывал нужные результаты при более чем одной паре r.id_row = '...' AND r.rows_val='...';

Смог найтие решеие задачи только двумя способоами:

1. С использованием sphinx, который это сможет.
2. С использованием мускула, но при каждом дополнительном параметре придётся делать дополнительный INNER JOIN:

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT SQL_CALC_FOUND_ROWS i.id
  2.  
  3. FROM items i
  4.  
  5. INNER JOIN rows r ON (r.id_item = i.id AND (r.id_row = '39' AND (r.rows_val = 3 )))
  6.  
  7. INNER JOIN rows rr ON (rr.id_item = i.id AND (rr.id_row ='50' AND rr.rows_val BETWEEN '70' AND '90'))
  8.  
  9. WHERE i.moder_status='active' ....прочие фильтры по полям таблицы items.


Минус варианта понятен, — INNER JOIN при каждом дополнительном параметре поиска (а их может быть и 10).


Подскажите эффективное решение.

(Отредактировано автором: 05 Марта, 2014 - 10:30:29)

 
 Top
Мелкий Супермодератор
Отправлено: 05 Марта, 2014 - 10:01:12
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Речь о том, что нужны id_item удовлетворяющие только пересечению всех условий?

Если не требуется наложение условий, по типу "для id_row=37 найти item_id, удовлетворяющие rows_val=1 и 2 одновременно", можно сделать так:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT id_item FROM TABLE WHERE
  2. (id_row = 39 AND rows_val = 70)
  3. OR  (id_row = 80 AND rows_val BETWEEN 70 AND 90)
  4. OR (id_row = 37 AND (rows_val = 1 OR rows_val = 2 OR rows_val >= 4))
  5. GROUP BY 1 HAVING count(DISTINCT id_row)=3

count в having должен сравниваться с ожидаемым количеством условий where

С товарами можно подзапрос и переджойнить
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM items JOIN (SELECT ...) filtered_items ON id_item=items.id


-----
PostgreSQL DBA
 
 Top
Zuldek
Отправлено: 05 Марта, 2014 - 10:11:27
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2122
Дата рег-ции: Июнь 2010  


Помог: 50 раз(а)




Мелкий пишет:
Если не требуется наложение условий, по типу "для id_row=37 найти item_id, удовлетворяющие rows_val=1 и 2 одновременно"

Именно это и требуется, к сожалению, но лишь для одного параметра.
То есть, допустим, есть десяток пар:
AND id_row = 37 AND rows_val = 2
AND id_row = 5 AND rows_val = 16
AND id_row = 45 AND rows_val = 'some-val'
AND id_row = 100 AND rows_val between 90 AND 54
...

И есть только один фильтр, для которого нужно:

AND id_row = 39 AND (rows_val = 2 OR rows_val = 3 OR rows_val >= 4)
(Добавление)

Вот думаю не лучше-ли сделать ещё отдельный join результирующей временной таблицы к rows для этого параметра?

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM items JOIN (
  2.  
  3.     SELECT id_item FROM TABLE WHERE
  4.     (id_row = 39 AND rows_val = 70)
  5.     OR  (id_row = 80 AND rows_val BETWEEN 70 AND 90)
  6.     OR (id_row = 37 AND (rows_val = 1 OR rows_val = 2 OR rows_val >= 4))
  7.     GROUP BY 1 HAVING count(DISTINCT id_row)=3
  8.  
  9. ) filtered_items ON id_item=items.id
  10.  
  11. INNER JOIN rows rr ON item.id = rr.id_item AND (rr.rows_val = 2 OR rr.rows_val = 3 OR rr.rows_val >= 4)

(Отредактировано автором: 05 Марта, 2014 - 10:25:17)

 
 Top
Мелкий Супермодератор
Отправлено: 05 Марта, 2014 - 10:27:16
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Zuldek пишет:
И есть только один дополнительный параметр (количество комнат)

Комнат ведь не может быть одновременно 2 и 3 у одного item, тогда мой вариант годится.

Например, id_row=199 - это вид из окна. val, например, представляет вид на реку, вид на лес. Мой вариант усложнится, если потребуется найти item с видом из окна на лес с рекой (т.е. одновременно виден и лес и река), а не на хотя бы что-нибудь одно из них.


-----
PostgreSQL DBA
 
 Top
Zuldek
Отправлено: 05 Марта, 2014 - 10:51:47
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2122
Дата рег-ции: Июнь 2010  


Помог: 50 раз(а)




Цитата:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM items JOIN (SELECT ...) filtered_items ON id_item=items.id


Мускел не знает о id_item в подзапросе. Не сработал join:

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT SQL_CALC_FOUND_ROWS i.id, i.title FROM items i JOIN (
  2.  
  3.     SELECT r.id_item FROM rows r WHERE
  4.     (r.id_row ='50' AND r.rows_val BETWEEN 70 AND 90)
  5.     OR (r.id_row = '39' AND r.rows_val = 3)
  6.     GROUP BY 1 HAVING count(DISTINCT r.id_row)=2
  7.  
  8. ) filtered_items ON r.id_item=i.id


upd. отработал без алиасов таблиц, спасибо
Спойлер (Отобразить)


Тем не менее, получается, что сами параметры со значениями придётся извлекать отдельным запросом или ещё одним подзапросом..

(Отредактировано автором: 05 Марта, 2014 - 11:30:15)

 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB