查询计算不同的组合

The*_*ter 6 sql algorithm math

首先,我为这个问题的标题道歉,我暂时没有更好的想法.提出一个很好的建议,我将修复标题.(如果我有权这样做,我实际上不知道.)

情况:

我很难完成正确的SQL查询.我有一个设置,人们可以下订单,产品等,并在某些情况下获得折扣.

请考虑以下架构:

Product:
  [...]

Price:
  product_id: integer
  description: string
  [...]

Order:
  [...]

OrderItem:
  order_id: integer
  price_id: integer
  amount: integer
Run Code Online (Sandbox Code Playgroud)

并考虑以下规则:

  • 有9种不同的产品.
  • 所有产品都有2个价格,一个描述PriceA,一个描述PriceB.
  • 每种产品的每种类型的价格都相同.(也就是说,所有PriceA价格都相同,且所有PriceB价格都相同.)

问题:

对于具有相同价格水平的每种5 种不同产品(即PriceA与PriceB),订单的总价格会降低一定数量.我正在尝试编写一个查询,告诉我发生了多少次.

例子:

示例1:
用户下订单:

  • 5次产品1,
  • 产品2倍,
  • 5次产品3,
  • 3次产品4,
  • 3次产品5.

所有在PriceA,客户获得3倍的折扣,因为有3套完整的5

示例2: 用户下订单:

  • 5次产品1,
  • 产品2倍,
  • 5次产品3,
  • 5次产品4,
  • 产品5倍,
  • 2次产品6,
  • 2次产品7

所有的PriceA价格.现在,客户获得5倍的折扣,因为有4套5个,2个涉及product5,2个涉及product6,1个涉及product7.

斗争:

我试过这个SQL:

SELECT min(amount) as amount from
    (SELECT oi.amount from `order` o
        inner join orderitem oi on oi.order_id = o.id
        inner join price p on oi.price_id = p.id AND p.description = "PriceA"
        inner join product pr on p.product_id = pr.id
        order by oi.amount desc
        limit 5) as z
    having count(amount) = 5;
Run Code Online (Sandbox Code Playgroud)

这非常适用于示例1,但在示例2中,它将给出错误的结果,因为它将选择第一组5个项目,然后忽略

问题是:这可以在SQL中解决吗?或者我会更好地扩大我的选择并通过脚本进行数学运算?(我的Web应用程序是用PHP编写的,所以我确实有一些服务器端数学的空间.)

解决方案:

我实施了Neil的解决方案; 它现在看起来像这样:

/** @var $oid integer The order ID. */

/* Select all amounts ordered per item, only for a given price title. */
$sql = <<<SQL
SELECT oi.amount as amount FROM orderitems oi
    INNER JOIN orders   o  ON oi.order_id  = o.id AND o.id = $oid
    INNER JOIN prices   p  ON oi.price_id  = p.id AND p.title = '%s'
    INNER JOIN products pr ON p.product_id = pr.id
    ORDER BY oi.amount DESC
SQL;
$discountInfo = array(
    array(
        'price'     => 'PriceA',
        'discounts' => array(
            9 => 49.50, /* Key is 'size of set', value is 'discount'. */
            5 => 23.50
        ),
    ),
    array(
        'price' => 'PriceB',
        'discounts'  => array(
            9 => 22,
            5 => 10,
        ),
    ),
);

foreach($discountInfo as $info)
{
    /* Store all ordered amounts per item in Array. */
    $arr = array();
    $result = $this->dbQuery(sprintf($sql,$info['price']));
    while ($row = mysql_fetch_assoc($result)) $arr[] = $row['amount'];

    foreach ($info['discounts'] as $am => $di)
    {
        /* For each highest set of $am items, fetch the smallest member. */
        while (count($arr) >= $am)
        {
            /* Add discount for each complete set */
            $discount += $di * $arr[$am - 1];

            /* Substract the amounts from all members of the set */
            for ($i=0; $i<=$am - 1; $i++) $arr[$i] -= $arr[$am - 1];

            /* Remove all elements that are 0 */
            foreach ($arr as $k=>$v) if ($v == 0) unset ($arr[$k]);

            /* Array is messed up now, re-sort and re-index it. */
            rsort($arr);
        } 
    } 
}
Run Code Online (Sandbox Code Playgroud)

Nei*_*eil 1

这就是我在代码中执行此操作的方式:将项目拆分为两个数组,每个数组对应一个价格级别。对于每个产品数组,数组中至少有五个产品:

  1. 按产品的项目数降序对数组进行排序
  2. 将数组中第五个产品的商品数量添加到折扣总数中
  3. 从数组中的前五个产品中减去数组中第五个产品的项目数
  4. 从数组中删除任何零元素