|
|
|
| Есть текстовое поле, куда пользователь должен ввести число. Когда он вводит это число и нажимает Submit из базы нужно достать от одного до 5 товаров, сумма цен которых равна введенному числу. Количество товаров - показатель рандомный, т.е. все время меняется.
У меня вопрос: выбирать по одному товару, смотреть его цену, отнимать от суммы, введенной пользователем, и смотреть остаток или можно как-то все вместе выбрать одним запросом? | |
|
|
|
|
|
|
|
для: Лена
(02.04.2015 в 16:04)
| | сколько всего отличающихся цен товаров в базе?
задача сильно напоминает задачу о ранце, а от последней хочется бежать. | |
|
|
|
|
|
|
|
для: Trianon
(02.04.2015 в 20:13)
| | Цены все разные. Или я ваш вопрос не поняла... | |
|
|
|
|
|
|
|
для: Лена
(02.04.2015 в 21:06)
| | >Цены все разные
В таком разе - сколько там всего товаров?
То, что все цены уникальные - несколько упрощает задачу. | |
|
|
|
|
|
|
|
для: Trianon
(02.04.2015 в 21:23)
| | нет, совпадение цены тоже может быть, т.е. 2 товара с одинаковой ценой, база же живая.
Я сейчас делаю на тестовом магазине, товаров там до 100, сколько будет в реальной базе, я не уточнила. | |
|
|
|
|
|
|
|
для: Лена
(02.04.2015 в 21:38)
| | Какая-то странная задача для реального магазина.... Я сначала подумал, что она учебная, либо тестовая.
Может сумма должна не превышать? Или вот прям равна один в один? | |
|
|
|
|
|
|
|
для: Sfinks
(02.04.2015 в 21:56)
| | нет, не один в один, должна не превышать.
Допустим, сумма $30. Можно выбрать товар за $20 и за $6. | |
|
|
|
|
|
|
|
для: Лена
(02.04.2015 в 22:02)
| | Лучше не решать это одним запросом.
Можно, но лучше не нужно.
Запрос будет очень тяжелым для сервера. На реальном количестве товаров сервер ляжет. | |
|
|
|
|
|
|
|
для: Sfinks
(02.04.2015 в 22:12)
| | я к этому тоже больше склонялась, одни товар взяли - посмотрели сколько осталось, если еще деньги есть - засовываем в массив второй товар. | |
|
|
|
|
|
|
|
для: Лена
(02.04.2015 в 22:15)
| | Даже не так...
сумма = 10000
израсходовано = 0
товары = []
цикл(от 0 до 4){
остаток = сумма - израсходовано
товар = "SELECT * FROM prices WHERE price <= {остаток} ORDER BY RAND() LIMIT 1"
если есть товар{
товары[] = товар
израсходовано += товар[price]
}
}
|
Я сам всегда говорю, что запрос в цикле - это зло! Но тут, мне кажется, стоит сделать исключение.
----------------
"даже не так" - я хотел сказать, что мы не смотрим есть ли еще деньги. Они почти всегда будут, т.к. наверняка сумма один в один не попадет. Вместо этого мы говорим базе смотреть есть ли товар за наш остаток. А так принцип тот же. | |
|
|
|
|
|
|
|
для: Sfinks
(02.04.2015 в 22:24)
| | Мне сдается, не нужен тут запрос в цикле.
Тут стоит вытащить отклик SELECT price, count(*) as qty FROM goods GROUP BY price ORDER BY price
в массив на уровень приложения, и работать уже без SQL.
Цен не так много в реальных базах. Хорошо если сотня тысяч наберется. | |
|
|
|
|
|
|
|
для: Trianon
(02.04.2015 в 23:00)
| | так а что дальше с ценами делать? Я на сколько понял, нужно не цены подобрать, а товары. А товаров может быть много. Их вытаскивать не резон. | |
|
|
|
|
|
|
|
для: Sfinks
(03.04.2015 в 07:20)
| | Нужно название товара, цена и id.
Спасибо за помощь, получилось вот что:
<?php
$digit = isset($_POST['digit'])? (int)$_POST['digit'] : 0;
if($digit) {
$products = $ids = array();
$title = $id = $price = '';
$spent = $rest = 0;
for($i=0; $i < 4; $i++) {
$rest = $digit - $spent;
if(count($ids) > 0) $ids_str = "AND p.ID NOT IN (" . implode(",",$ids) . ")";
else $ids_str = '';
$query = "SELECT p.ID, p.post_title,pm.meta_value FROM wp_posts p
LEFT JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type='wpsc-product'
AND pm.meta_key = '_wpsc_price'
AND pm.meta_value <= " . $rest . " " .
$ids_str . "
ORDER by RAND() LIMIT 1";
if($rest > 0) {
$result = $mysqli->query($query);
if ($result->field_count > 0) {
$row = $result->fetch_assoc();
$title = $row["post_title"];
$price = number_format($row["meta_value"]);
$id = $row["ID"];
$products[] = array("id"=>$id,"title"=>$title,"price"=>$price);
$ids[] = $id;
$spent += $price;
}
}
}
$result->free();
$mysqli->close();
print json_encode($products);
exit;
}
?>
|
| |
|
|
|
|
|
|
|
для: Sfinks
(03.04.2015 в 07:20)
| | Основная вычислительная сложность перебора цен не затрагивает ключи товаров. И она же сильно падает с сокращением множества цен. Так что есть смысл оптимизировать этот процесс, отойдя от товаров.
Товары по подобранным ценам можно потом получить быстрыми одиночными запросами (понятно, если построен индекс на поле price) | |
|
|
|
|
|
|
|
для: Trianon
(03.04.2015 в 20:13)
| | я три раза перечитала и все равно не сильно поняла. Выбирать только цены, а после выбора цен уже получать id товара и его название еще одним запросом? | |
|
|
|
|
|
|
|
для: Лена
(04.04.2015 в 14:24)
| | Да. Может быть даже не одним. Так или иначе это будут достаточно простые запросы.
Если уникальных цен, к примеру, в 20 раз меньше чем товаров, то число циклов перебора сократится в 20 в степени числа кругов. Мне представляется это изрядной .экономией.
Вообще-то изначально задача воспринималась, как подбор ряда товаров, суммарная стоимость которых строго соответствует запрошенной, а не просто не превышает последнюю. Это куда более длительный перебор.
Поиск оптимального набора тоже задача не из быстрых. | |
|
|
|
|
|
|
|
для: Trianon
(04.04.2015 в 18:02)
| | Мне так и сказали: желательно сделать точную цену. Пока у меня идей никаких нет.
Мне в голову только запрос вот такой пришел:
SET @count := 5; # сколько товаров надо выбрать
SET @sum := 100; # на какую сумму выбрать
SELECT * FROM product p WHERE (@sum := @sum - p.price) > 0 AND
(@count := @count - 1) > 0 ORDER BY RAND() DESC | |
|
|
|
|
|
|
|
для: Лена
(07.04.2015 в 19:08)
| | >Мне так и сказали: желательно сделать точную цену. Пока у меня идей никаких нет.
см мой пост 02.04.2015 22:00МСК
Чтобы было быстро, надо уходить от товаров в цены, и от SQL в чистые вычисления.
Все же это задача не для БД. | |
|
|
|
|
|
|
|
для: Sfinks
(02.04.2015 в 21:56)
| | явно какая-то маркетинговая завлекалочка в духе
"Скажи, сколько у тебя в кошельке, и мы подскажем, как их оптимально просадить за раз, так чтоб никакая жена/налоговая не успела отобрать кровное." | |
|
|
|
|
|
|
|
для: Trianon
(02.04.2015 в 22:04)
| | компания да, маркетинговая ))) а что они с этим делать будут, мне не сообщили, озвучили только "for internal purposes of the company" | |
|
|
|
|
|
|
|
для: Лена
(02.04.2015 в 21:38)
| | примерный алгоритм таков.
Только работать он будет ... Скажем так, куда дольше самого магазина.
select_good_set(sum, level)
{
if(!--level) return find(sum, sum);
while(a = find(goods, 1, sum - level))
{
goods.remove(a);
if(r = select_good_set(sum-a.price(), level))
return(list(a, r));
goods.add(a);
}
return 0;
}
|
| |
|
|
|