Организация структуры таблиц БД, содержащих информацию о скидках на товары.

Гриша К.

Новичок
Организация структуры таблиц БД, содержащих информацию о скидках на товары.

Здравствуйте.

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

Предполагаю в итоге сделать так:
1) Скидку можно установить для всех товаров категории
2) Скидку можно установить для выбранных товаров

PHP:
PRODUCTS
product_id | category_id | product_name 
    1            1           Книга

PRICES
price_id | product_id | price
    1          1        1000.00
    2          1        1200.00
#:: Цена товара завист от различных опций, цвет, размер и т. д., поэтому один товар может иметь несколько цен.
Практических идей никаких даже не получается, начинаю пытаться сделать на бумаге,
и просто незнаю даже с чего начать, ничего невыходит.

Уже 8 часов пытаюсь на бумаге написать структуру, просто не одной идеи, это решение меня вогнало в с тупор.
 

akd

dive now, work later
Команда форума
tblDiscount - скидки
tblCategoryDiscount - связь скидка/категория
tblProductDiscount - связь скидка/товар
 

clevel

Новичок
ой! зачем там все усложнять:

category
good
discount

если category = 0 , значит скидка на конкретный товар, и по аналогии - good=0 - скидка на категорию..
 

akd

dive now, work later
Команда форума
clevel ну ... как по мне так лучше 3 таблицы, чем одна избыточная.
но это личное дело каждого конечно :)
 

Андрейка

Senior pomidor developer
akd
покажи запрос на список товаров + скидка для текущего покупателя плиз?
 

akd

dive now, work later
Команда форума
Андрейка, может сразу весь магазин написать? :)
 

Андрейка

Senior pomidor developer
akd
если честно - мне лично пофик - можешь и написать %)

а вообще - мы принимаем важнейшее решение о структуре базы гражданина Гриша К. - ошибицца тут нельзя, поэтому хотелось бы понять какие преимущества имеет ваша структура и как вообще под нее запрос написать?
 

akd

dive now, work later
Команда форума
Андрейка, я, если честно, не вижу смысла здесь упражняться в составлении запросов.
думаю, что гражданин Гриша К. в состоянии сам выбрать какой из двух вариантов ему подходит и написать нужные запросы.
как-то так :)
 

Гриша К.

Новичок
Спасибо большое всем за ответы.
Вот появился вариант решения, в составление запроса.

Структура таблиц БД содержащих информацию о скидках:
PHP:
DISCOUNTS (discount_id, discount)
DISCOUNT_CATEGORY (discount_id, category_id)
DISCOUNT_PRODUCT (discount_id, product_id)
Запрос к БД, и вычитание скидки
PHP:
SELECT 
    * # Перечесляю нужные поля 
FROM 
    products 
    LEFT JOIN categories on products.category_id = categories.category_id     
    LEFT JOIN prices on products.product_id = prices.product_id             
    LEFT JOIN photos on products.product_id = photos.product_id 

    LEFT JOIN discount_product on products.product_id = discount_product.product_id 
    LEFT JOIN discount_category on products.category_id = discount_category.category_id
    LEFT JOIN discounts on discount_product.discount_id = discounts.discount_id OR 
    discount_category.discount_id = discounts.discount_id
    # Объеденение левостороннее, потому что фотографий для товара может не быть                     
WHERE 
    # Условия, сортировка 


// Собираю массив с данными товаров 
for ($count=0; $row = mysql_fetch_assoc($result); $count++) 
{
     // Проверяю есть ли скидка  
    if(!empty($row['discount_category']) && $row['discount_category'] == $row['category_id'])
            $row['price_new'] = $row['price'] - $row['price'] * $row['discount'] / 100;
    elseif(!empty($row['discount_product']) && $row['discount_product'] == $row['product_id'])
            $row['price_new'] = $row['price'] - $row['price'] * $row['discount'] / 100;

    $row['price_new'] = (!empty($row['price_new'])) ? number_format($row['price_new'], 2) : '';   
    
    $result_array[$row['product_id']] = $row; 
}
Возможно еще вы мне сможете подсказать, насколько запрос такого рода может быть тяжелым для БД, опыта я не имею вобщем-то, поэтому незнаю запросы такого рода, с большим количество LEF JOIN, загружают ли очень сильно БД (вот например почитав про like '%like%', я понял какой это тяжеленный запрос.)?
 

akd

dive now, work later
Команда форума
Гриша К., у тебя странным образом (мне непонятно зачем) в одном месте и скидки и цены и фотографии. :)
не думаю, что это стоит так делать даже не из-за скорости, а просто из-за логики. :)
 

Гриша К.

Новичок
akd, спасибо за ответ.

Данный запрос извлекает постранично данные 15 товаров (в запросе присутствует LIMIT): название, описание, цену по умолчанию (цен может быть несколько в зависимости от опций товара), скидку, фотографию по умолчанию (фотографий может быть несколько).

Далее собираю циклом массив с данными товара, в этом же цикле сразу подсчитываю цену со скидкой.

Если я к примеру разобью этот запрос на 3:
- 1 извлекает: название, описание
- 2 извлекает: цену по умолчанию, скидку
- 3 извлекает: фотографию по умолчанию

На странице теперь получится 3 запроса и 3 цикла,
будет ли такой вариант, в плане скорости, нагрузки на БД лучше чем в 1 запросе?

И в каждом запросе мне придется использовать объединение с таблицей товаров и категорий,
чтобы извлекать товары для опеределнных категорий (и подкатегорий),
и для пользователей не имеющих соответсвующих привилегий ивзлеакть
данные для незакрытых категорий и товаров:
PHP:
SELECT  
    * # Перечесляю нужные поля  
FROM  
    products  
    LEFT JOIN categories on products.category_id = categories.category_id               
    LEFT JOIN photos on products.product_id = photos.product_id  
    # Объеденение левостороннее, потому что фотографий для товара может не быть                      
WHERE  
    # Условия, сортировка
 

akd

dive now, work later
Команда форума
Гриша К., ааа .. про умолчание цен и фоток там ни слова небыло.

вообщем можно все одним запросом, если правильно расставлены индексы.

зы. цену со скидкой можно считать прямо в запросе.
 

Гриша К.

Новичок
akd, спасибо за ответ.

Для извлечения например фотографии по умолчанию, необходимо одно условие photo_default = 1, поэтому думаю это не влияет на трудности при разделении запроса.

Вот при разделении запроса меня начинает волновать тот факт, что мне придется в 3-х запросах, обращаться к 2-м одним и тем же таблицам, как поступить в таком случае, разделять или нет?
 

akd

dive now, work later
Команда форума
Гриша К., ответ один: тестируй. :)
 

Гриша К.

Новичок
akd, да тоже вариант ))
Буду думать

-~{}~ 04.10.06 18:25:

Делаю отдельный запрос для извлечения цены и скидки, если она есть.
Таблицы:
PHP:
PRODUCTS (product_id, category_id, product_name)
PRICES (price_id, product_id, price)
DISCOUNTS (discount_id, discount) 
DISCOUNT_CATEGORY (discount_id, category_id) 
DISCOUNT_PRODUCT (discount_id, product_id)
PHP:
# Запрос:
SELECT	
	* #Перечесляю нужные поля
FROM 
	products
	LEFT JOIN prices ON products.product_id = prices.product_id			
	LEFT JOIN discount_product on products.product_id = discount_product.product_id 
	LEFT JOIN discount_category on products.category_id = discount_category.category_id
	LEFT JOIN discount_partner on products.partner_id = discount_partner.partner_id
	LEFT JOIN discounts on discount_product.discount_id = discounts.discount_id OR 
		                     discount_category.discount_id = discounts.discount_id			
WHERE
	products.product_id IN(0,5,7,8,10,11,12) AND
	price_default = 1
PHP:
# EXPLAIN:
id | select_type | table  	         | type  | possible_keys | key         | key_len | ref                                   rows  Extra  
1    SIMPLE        products 		   index   PRIMARY         category_id   4         NULL 				  9    Using where; Using index	  
1    SIMPLE        discount_product 	   ref     product_id      product_id    4         pozvono9_magazin.products.product_id   1   
1    SIMPLE        discount_category 	   ref     category_id     category_id   4         pozvono9_magazin.products.category_id  1   
1    SIMPLE        prices                  ref     product_id 	   product_id    4         pozvono9_magazin.products.product_id   1    Using where 
1    SIMPLE        discounts 		   ALL     PRIMARY         NULL          NULL      NULL                                   3
Значит число просматриваемых строк в данном случа будет 9*3 = 27, а если товаров будет хотябы 1000, а скидок 10, то 1000*10 = 10000 и т.д.

Подскажите пожалуйста варианты оптимизации (составления) данного запроса
 

akd

dive now, work later
Команда форума
где и как часто ты собираешься выводить 1000 товаров? :)

ПС. а почему вот это получилось "products.product_id IN(0,5,7,8,10,11,12)

ПС2. преждевременная оптимизация зло. наполни базу тестовыми данными и посмотри как будут выполнять обычные запросы, оттуда уже и танцевать с бубном можно начинать, если потребуется.
 

Гриша К.

Новичок
akd, спасибо за ответ.
Выводить на странице я буду по 15 товаров, +- 5.

У меня получается 3 запроса к БД:
1) Извлекаю данные товара, определяю порядок сортировки (FROM products, categories, prices).
$products_array - массив данных товаров (ключ - ИД товара).
$list_product_id - ИД извлеченных товаров
2) Извлекаю ИД фотографий товаров (FROM photos WHERE photos.product_id IN($list_product_id))
3) Извлекаю Цену товара, скидку, курс валюты, затем складываю и считаю (не в запросе, приходится делать некоторые проверки) - запрос который описан выше.
(WHERE products.product_id IN($list_product_id)) == products.product_id IN(0,5,7,8,10,11,12)

ПС2. преждевременная оптимизация зло. наполни базу тестовыми данными и посмотри как будут выполнять обычные запросы, оттуда уже и танцевать с бубном можно начинать, если потребуется.
Все правильно, я так и сделаю. Неправильно я поступил, надо было сначала заполнить, посмотреть, а потом на форум вопросы задавать.
 
Сверху