【问题标题】:Add a condition to MySQL JOIN query: WHERE a column equals to result of a query向 MySQL JOIN 查询添加条件:WHERE 列等于查询结果
【发布时间】:2017-11-29 15:03:17
【问题描述】:

在电子商务网站中,我必须更改查询。 本网站对每种产品有多种价格,具体取决于客户选择的数量。

如果购物车中的产品数量超过特定数量,则其成本会更低。

例如,如果数量为 1,则价格为 10 美元,如果数量为 20,则每个产品的价格将降低到 8 美元。

这是我的表结构:

prices
id | product_id | num | price
1  | 111111     | 1   | 10
2  | 111111     | 20  | 8
3  | 111111     | 100 | 5
4  | 222222     | 1   | 42
5  | 222222     | 50  | 35

cart

id | factor_id | product_id | quantity
1  | 1         | 111111       | 30
2  | 1         | 222222       | 3
3  | 2         | 222222       | 1
4  | 2         | 111111       | 2

在这个查询中:

SELECT prices.price AS price, prices.product_id AS product_id FROM cart
LEFT JOIN prices ON prices.product_id = cart.product_id  
WHERE prices.num='1'
AND cart.id='$cart_id'

我想更改WHERE prices.num='1' 行。价格必须根据购物车中该产品的数量来选择。

我认为这样的事情可能会有所帮助,但我不知道如何使用它,因为每个购物车可以有不同的产品:

SELECT (prices.num - cart.quantity) as nearest, prices.num as priceForThatQuantity
FROM prices
WHERE nearest > 0
ORDER BY nearest ASC
LIMIT 1

然后:

WHERE prices.num='1' = priceForThatQuantity

我想我必须使用某种 JOIN...

编辑: 产品111111 的数量少于 20 件时为 10 美元,数量在 20 到 100 件之间时为 8 美元,超过 100 件时为 5 美元。

【问题讨论】:

  • 每增加一个产品,每个减少多少?那是一张桌子吗?还是固定费率?
  • 不幸的是,减量不是固定的。它们存储在prices 表中。在num 列中。
  • 请提供一些示例数据,是百分比还是美元金额?折扣数量有限制吗?是每减一减吗?这里有很多没有定义。
  • 一个产品可以有两个以上的价格吗?
  • 如您在prices111111 中看到的,如果数量少于 20 个,产品价格为 10 美元,数量在 20 到 100 个之间为 8 美元,超过 100 件为 5 美元。

标签: php mysql e-commerce


【解决方案1】:

什么唯一标识cart 中的一行? (id,product_id)的组合?

一个选项是使用 GROUP BY 和 MIN() 聚合的 JOIN,以从 cart 中的匹配行中挑选出最低价格。但是,如果 cart 中的行没有保证唯一性,我会犹豫是否将 GROUP BY 添加到查询中,冒着折叠行的风险。

因此,更安全的选择是 SELECT 列表中的相关子查询。 (这对于大型集合不太理想,但考虑到示例查询正在检索单个购物车,并且购物车中的商品数量可能相当少,并且在 price 表上有合适的索引可用,这不会受到伤害我们在性能方面太糟糕了,就像使用大集合一样。

我们可以这样做:

 SELECT ( SELECT price.unit_price
            FROM price
           WHERE price.product_id = cart.product_id
             AND price.num       <= cart.quantity
           ORDER BY price.num DESC
           LIMIT 1
        ) AS unit_price
      , cart.product_id AS product_id
   FROM cart
  WHERE cart.id = 'foo'

请注意,price 表中有可能匹配多行,如果购物车的数量为 '20',我们可以匹配 price 中的行,因为 num 的值为 15,@ 987654332@、631 ... 所以我们需要一种方法来“挑选”哪些行要使用。一种方法是按num 降序排列匹配的行,并且只取第一行。这就是上面的查询所做的,在子查询中有 ORDER BY 和 LIMIT 1。


回到 JOIN 选项...

除非保证price 中的行具有与quantity 的每个可能值匹配的num 值,否则我们可能需要在价格中查找具有小于num 值的行大于或等于quantity

在 JOIN 中使用该条件时,可能会匹配多行。以下查询有可能从cart 返回重复的product_id,这不会返回“正确”结果,但将演示当quantity“匹配”多个值时我们通过JOIN 操作获得的结果num...

SELECT cart.product_id
     , price.num
     , price.unit_price
  FROM cart 
  JOIN price 
    ON price.product_id  = cart.product_id
   AND price.num        <= cart.quantity 
 WHERE cart.id = 'foo'
 ORDER BY 1,2,3

我们可以使用GROUP BY 来折叠行并使用聚合函数来挑选最低价格。 (假设数量越多价格越低。假设数量越少,单价越低,我们可以得到我们匹配的最高值num和最低值price

SELECT cart.product_id
     , MAX(price.num)
     , MIN(price.unit_price)
  FROM cart 
  JOIN price 
    ON price.product_id  = cart.product_id
   AND price.num        <= cart.quantity 
 WHERE cart.id = 'foo'
 GROUP BY cart.id, cart.product_id
 ORDER BY cart.id, cart.product_id

【讨论】:

    【解决方案2】:

    从这个查询开始:

     SELECT *
     FROM cart c
     JOIN prices p
       ON c.product_id = p.product_id
      AND c.quantity >= p.num 
    

    您可以看到产品 111111 30 > 1 和 30 > 20,因此您需要将它们分组并获得最低价格以获得 8 美元

     SELECT c.product_id, 
            c.quantity,
            MIN(p.price) as price
     FROM cart c
     JOIN prices p
       ON c.product_id = p.product_id
      AND c.quantity >= p.num 
     GROUP BY  c.product_id, 
               c.quantity
    

    【讨论】:

      【解决方案3】:

      试试:

      SELECT prices.price AS price, prices.product_id AS product_id FROM cart
      LEFT JOIN prices ON prices.product_id = cart.product_id  
      WHERE prices.num in ( SELECT quantity FROM cart WHERE cart.id='$cart_id')
      AND cart.id='$cart_id'
      

      【讨论】:

      • 这不是我想要的,一个用户可以订购 16 件产品 111111,并且在数据库中有 1 件或更多件的行,20 件或更多件......。在这种情况下,计算 1 件或更多件的价格,显然是因为 16 件小于 20。
      猜你喜欢
      • 1970-01-01
      • 2014-07-09
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      • 2013-01-16
      • 2017-01-16
      • 1970-01-01
      相关资源
      最近更新 更多