Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум (новые сообщения вниз) Структурный форум

тема: Узнать количество товара с определенными параметрами

Сообщения:  [1-10]   [11-16] 

 
 автор: Ученик   (23.07.2010 в 17:48)   письмо автору
 
   для: sms-send   (23.07.2010 в 16:34)
 

Собственно для чего задумывалось это все извращение.
В первую очередь не для того чтобы фильтровать, исходя из значений параметров. А чтобы можно было вывести количество товаров у которых параметр равен одному из вариантов его значения

Цвет
 белый 160
 черный 100
 синий 20
 фиолетовый 20
Материал
 хлопок 200
 мешковина 1
 шелк 40
 синтетика 59


Собственно такой вариант решается простым IF
SUM(IF(`param_id` = 2 AND `value` = "белый", 1, 0)) as "2.белый",
SUM(IF(`param_id` = 2 AND `value` = "черный ", 1, 0)) as "2.черный ",
SUM(IF(`param_id` = 2 AND `value` = "синий ", 1, 0)) as "2.синий ",


Но, еще к этому нужно вывести вот такой вариант
Качество майки
 Хорошее(цвет белый,черный,синий + материал хлопок, шелк) 240
 Среднее(цвет любой, материал синтетика) 59
 Плохое(цвет любой, материал мешковина ) 1

Это как раз таки составной фильтр, и его нельзя сделать в одном запросе с IF. Вот если все параметры в виде колонок, то легко.

Надеюсь я не намудрил с объяснением

  Ответить  
 
 автор: sms-send   (23.07.2010 в 16:34)   письмо автору
 
   для: Ученик   (23.07.2010 в 15:46)
 

Если запрос формируется на основании поисковой формы, то самое простое - ограничить пользователя в количестве задаваемых условий поиска (всё равно десяток-другой фиксированных параметров скорей всего обрежет множество до 0).

Количество JOIN'ов в данном запросе можно сократить в 2 раза, если заранее выбрать все используемые идентификаторы параметров из таблицы `params` и подставлять их в запрос "вручную".

Если 60 параметров мало, можно выполнять запросы по 60 JOIN'ов, а потом пересекать полученные товары по полю `tovar`.`tovar_id`.
SELECT *
FROM
    `tovar`
WHERE
    `tovar_id` IN (SELECT `tovar_id` FROM ... запрос с первыми 60 параметрами)
    AND
    `tovar_id` IN (SELECT `tovar_id` FROM ... запрос со вторыми 60 параметрами) 


Можно отказаться от гибкости и пустить таблицу `tovar` на денормализацию расти в ширину - для каждого аттрибута создать отдельное поле. Если у какого то товара не будет конкретного аттрибута, то в соответствующем поле будет NULL. Но врятли такую кучу можно будет заставить быстро работать.

  Ответить  
 
 автор: Ученик   (23.07.2010 в 15:46)   письмо автору
 
   для: Ученик   (23.07.2010 в 11:36)
 

Может вы еще подскажите как решить проблему если у товара больше 30 параметров?
Иначе рискуем увидеть такое сообщение
mysql can only use 61 tables in a join


Кстати запрос на реальной базе в сотни тысяч товаров, и миллионы параметров выполняется довольно быстро)

  Ответить  
 
 автор: Ученик   (23.07.2010 в 11:36)   письмо автору
 
   для: sms-send   (23.07.2010 в 10:57)
 

Спасибо большое, все оказалось и правда просто.
Признаюсь честно даже не знал что можно использовать такую конструкцию
(`param1`.`param_name`, `param1_val`.`param_value`)=("цвет", "белый")


PS В вашем коде есть небольшая опечатка, но кому этот запрос пригодится думаю разберутся в чем проблема;)

  Ответить  
 
 автор: sms-send   (23.07.2010 в 11:15)   письмо автору
 
   для: Trianon   (23.07.2010 в 11:08)
 

Соглашусь.
Но так будет удобней условие выборки формировать в одном месте:

(`param1`.`param_name`, `param1_val`.`param_value`)=("цвет", "чёрный")
AND 
(`param2`.`param_name`, `param2_val`.`param_value`)=("материал", "мешковина")


Если бы было:
INNER JOIN `tovar_params` AS `param_color_val` ON `tovar`.`tovar_id`=`param_color_val`.`tovar_id` 
INNER JOIN `params` as `param_color` ON `param_color_val`.`param_id`=`param_color`.`param_id`
согласился бы без возражений.

  Ответить  
 
 автор: Trianon   (23.07.2010 в 11:08)   письмо автору
 
   для: sms-send   (23.07.2010 в 10:57)
 

вот тут куски условий, живущие в WHERE ну просто в голос кричат "Переселите нас в соотв.join-ON!"

  Ответить  
 
 автор: sms-send   (23.07.2010 в 10:57)   письмо автору
 
   для: Ученик   (23.07.2010 в 01:04)
 

> Если бы она была в виде колонок, было бы совсем просто.
SELECT
    `tovar`.*,
    `param1_val`.`param_value` AS `цвет`,
    `param2_val`.`param_value` AS `материал`
FROM
    `tovar`
    INNER JOIN `tovar_params` AS `param1_val` ON `tovar`.`tovar_id`=`param1`.`tovar_id`
    INNER JOIN `params` as `param1` ON `param1_val`.`param_id`=`param1`.`param_id`
    INNER JOIN `tovar_params` AS `param2_val` ON `tovar`.`tovar_id`=`param2_val`.`tovar_id`
    INNER JOIN `params` as `param2` ON `param2_val`.`param_id`=`param2`.`param_id`
WHERE
    `param1`.`param_name`="цвет"
    AND
    `param2`.`param_name`="материал"

  Ответить  
 
 автор: Лена   (23.07.2010 в 10:30)   письмо автору
 
   для: sms-send   (23.07.2010 в 10:18)
 

Вот видите, когда вас и Trianon`a нет, ошибки некому поправить :)))


SELECT COUNT( * ) cnt
FROM tovar t
LEFT JOIN tovar_params tp ON tp.tovar_id = t.tovar_id
LEFT JOIN params pr ON pr.param_id = tp.param_id
WHERE (tp.param_value = 'белый'
OR tp.param_value = 'мешковина' ) AND pr.param_id IN(3,4,5,6)

  Ответить  
 
 автор: sms-send   (23.07.2010 в 10:18)   письмо автору
 
   для: Лена   (23.07.2010 в 10:05)
 

WHERE tp.param_value = 'белый' 
AND tp.param_value = 'мешковина'


tp.param_value должен разорваться и принимать одновременно (AND) два разных значения?))

  Ответить  
 
 автор: Лена   (23.07.2010 в 10:05)   письмо автору
 
   для: Ученик   (23.07.2010 в 01:04)
 

>Смотрите
>param_id 2 это цвет
>param_id 3 это материал
>В вашем последнем запросе это не учтено, но если и добавить
>
WHERE (tp.param_value = 'белый' AND pr.param_id = 2)
>AND (tp.param_value = 'мешковина' AND pr.param_id = 3)


Ну я вам разве так говорила...
SELECT COUNT( * ) cnt
FROM tovar t
LEFT JOIN tovar_params tp ON tp.tovar_id = t.tovar_id
LEFT JOIN params pr ON pr.param_id = tp.param_id
WHERE tp.param_value = 'белый'
AND tp.param_value = 'мешковина' AND pr.param_id IN(3,4,5,6)

  Ответить  

Сообщения:  [1-10]   [11-16] 

Форум разработан IT-студией SoftTime
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования