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

Форум PHP

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

 

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

вид форума:
Линейный форум Структурный форум

тема: Сумма случайных чисел
 
 автор: Лена   (02.04.2015 в 16:04)   письмо автору
 
 

Есть текстовое поле, куда пользователь должен ввести число. Когда он вводит это число и нажимает Submit из базы нужно достать от одного до 5 товаров, сумма цен которых равна введенному числу. Количество товаров - показатель рандомный, т.е. все время меняется.
У меня вопрос: выбирать по одному товару, смотреть его цену, отнимать от суммы, введенной пользователем, и смотреть остаток или можно как-то все вместе выбрать одним запросом?

  Ответить  
 
 автор: Trianon   (02.04.2015 в 20:13)   письмо автору
 
   для: Лена   (02.04.2015 в 16:04)
 

сколько всего отличающихся цен товаров в базе?

задача сильно напоминает задачу о ранце, а от последней хочется бежать.

  Ответить  
 
 автор: Лена   (02.04.2015 в 21:06)   письмо автору
 
   для: Trianon   (02.04.2015 в 20:13)
 

Цены все разные. Или я ваш вопрос не поняла...

  Ответить  
 
 автор: Trianon   (02.04.2015 в 21:23)   письмо автору
 
   для: Лена   (02.04.2015 в 21:06)
 

>Цены все разные

В таком разе - сколько там всего товаров?

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

  Ответить  
 
 автор: Лена   (02.04.2015 в 21:38)   письмо автору
 
   для: Trianon   (02.04.2015 в 21:23)
 

нет, совпадение цены тоже может быть, т.е. 2 товара с одинаковой ценой, база же живая.
Я сейчас делаю на тестовом магазине, товаров там до 100, сколько будет в реальной базе, я не уточнила.

  Ответить  
 
 автор: Sfinks   (02.04.2015 в 21:56)   письмо автору
 
   для: Лена   (02.04.2015 в 21:38)
 

Какая-то странная задача для реального магазина.... Я сначала подумал, что она учебная, либо тестовая.
Может сумма должна не превышать? Или вот прям равна один в один?

  Ответить  
 
 автор: Лена   (02.04.2015 в 22:02)   письмо автору
 
   для: Sfinks   (02.04.2015 в 21:56)
 

нет, не один в один, должна не превышать.
Допустим, сумма $30. Можно выбрать товар за $20 и за $6.

  Ответить  
 
 автор: Sfinks   (02.04.2015 в 22:12)   письмо автору
 
   для: Лена   (02.04.2015 в 22:02)
 

Лучше не решать это одним запросом.
Можно, но лучше не нужно.
Запрос будет очень тяжелым для сервера. На реальном количестве товаров сервер ляжет.

  Ответить  
 
 автор: Лена   (02.04.2015 в 22:15)   письмо автору
 
   для: Sfinks   (02.04.2015 в 22:12)
 

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

  Ответить  
 
 автор: Sfinks   (02.04.2015 в 22:24)   письмо автору
 
   для: Лена   (02.04.2015 в 22:15)
 

Даже не так...
сумма = 10000
израсходовано = 0
товары = []
цикл(от 0 до 4){
  остаток = сумма - израсходовано
  товар = "SELECT * FROM prices WHERE price <= {остаток} ORDER BY RAND() LIMIT 1"
  если есть товар{
    товары[] = товар
    израсходовано += товар[price]
  }
}

Я сам всегда говорю, что запрос в цикле - это зло! Но тут, мне кажется, стоит сделать исключение.
----------------
"даже не так" - я хотел сказать, что мы не смотрим есть ли еще деньги. Они почти всегда будут, т.к. наверняка сумма один в один не попадет. Вместо этого мы говорим базе смотреть есть ли товар за наш остаток. А так принцип тот же.

  Ответить  
 
 автор: Trianon   (02.04.2015 в 23:00)   письмо автору
 
   для: Sfinks   (02.04.2015 в 22:24)
 

Мне сдается, не нужен тут запрос в цикле.
Тут стоит вытащить отклик SELECT price, count(*) as qty FROM goods GROUP BY price ORDER BY price
в массив на уровень приложения, и работать уже без SQL.
Цен не так много в реальных базах. Хорошо если сотня тысяч наберется.

  Ответить  
 
 автор: Sfinks   (03.04.2015 в 07:20)   письмо автору
 
   для: Trianon   (02.04.2015 в 23:00)
 

так а что дальше с ценами делать? Я на сколько понял, нужно не цены подобрать, а товары. А товаров может быть много. Их вытаскивать не резон.

  Ответить  
 
 автор: Лена   (03.04.2015 в 08:36)   письмо автору
 
   для: 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;
    }
?>

  Ответить  
 
 автор: Trianon   (03.04.2015 в 20:13)   письмо автору
 
   для: Sfinks   (03.04.2015 в 07:20)
 

Основная вычислительная сложность перебора цен не затрагивает ключи товаров. И она же сильно падает с сокращением множества цен. Так что есть смысл оптимизировать этот процесс, отойдя от товаров.
Товары по подобранным ценам можно потом получить быстрыми одиночными запросами (понятно, если построен индекс на поле price)

  Ответить  
 
 автор: Лена   (04.04.2015 в 14:24)   письмо автору
 
   для: Trianon   (03.04.2015 в 20:13)
 

я три раза перечитала и все равно не сильно поняла. Выбирать только цены, а после выбора цен уже получать id товара и его название еще одним запросом?

  Ответить  
 
 автор: Trianon   (04.04.2015 в 18:02)   письмо автору
 
   для: Лена   (04.04.2015 в 14:24)
 

Да. Может быть даже не одним. Так или иначе это будут достаточно простые запросы.
Если уникальных цен, к примеру, в 20 раз меньше чем товаров, то число циклов перебора сократится в 20 в степени числа кругов. Мне представляется это изрядной .экономией.


Вообще-то изначально задача воспринималась, как подбор ряда товаров, суммарная стоимость которых строго соответствует запрошенной, а не просто не превышает последнюю. Это куда более длительный перебор.
Поиск оптимального набора тоже задача не из быстрых.

  Ответить  
 
 автор: Лена   (07.04.2015 в 19:08)   письмо автору
 
   для: 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

  Ответить  
 
 автор: Trianon   (08.04.2015 в 23:11)   письмо автору
 
   для: Лена   (07.04.2015 в 19:08)
 

>Мне так и сказали: желательно сделать точную цену. Пока у меня идей никаких нет.
см мой пост 02.04.2015 22:00МСК
Чтобы было быстро, надо уходить от товаров в цены, и от SQL в чистые вычисления.
Все же это задача не для БД.

  Ответить  
 
 автор: Trianon   (02.04.2015 в 22:04)   письмо автору
 
   для: Sfinks   (02.04.2015 в 21:56)
 

явно какая-то маркетинговая завлекалочка в духе
"Скажи, сколько у тебя в кошельке, и мы подскажем, как их оптимально просадить за раз, так чтоб никакая жена/налоговая не успела отобрать кровное."

  Ответить  
 
 автор: Лена   (02.04.2015 в 22:10)   письмо автору
 
   для: Trianon   (02.04.2015 в 22:04)
 

компания да, маркетинговая ))) а что они с этим делать будут, мне не сообщили, озвучили только "for internal purposes of the company"

  Ответить  
 
 автор: Trianon   (02.04.2015 в 22:00)   письмо автору
 
   для: Лена   (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;
}

  Ответить  
Rambler's Top100
вверх

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