2

我想检索所有产品的列表,以及给定时期的相关价格。

产品表:

Id
Name
Description

价格表:

Id 
Product_id
Name
Amount
Start
End
Duration

最重要的是,一个产品可以有多个价格,即使是在同一时期,但不是在相同的持续时间。例如,“2013-06-01 -> 2013-06-08”的价格和“2013-06-01 -> 2013-06-05”的价格

所以我的目标是在给定的时期内检索所有产品的列表,例如按 10 个产品分页,并加入该时期内存在的价格。

这样做的基本方法是:

SElECT *
FROM product
LEFT JOIN prices ON ...
WHERE prices.start >= XXX And prices.end <= YYY
LIMIT 0,10

使用这个简单的解决方案时的问题是,我不能只检索 10 个产品,而是 10 个产品*价格,这在我的情况下是不可接受的。

所以解决方案是:

SElECT *
FROM product
LEFT JOIN prices ON ...
WHERE prices.start >= XXX And prices.end <= YYY
GROUP BY product.id
LIMIT 0,10

但这里的问题是,我只会为每个产品检索“1”价格。

所以我想知道处理这个问题的最佳方法是什么。例如,我可以使用组函数,如 "group_concat",并在字段中检索字符串中的所有价格,如 "200/300/100" 等等。这看起来很奇怪,需要在服务器语言端进行工作才能转换为可读信息,但它可以工作。

另一种解决方案是为每个价格使用不同的列,具体取决于持续时间:

SELECT 
   IF( NOT ISNULL(price.start) AND price.duration = 1, price.amount , NULL) AS price_1_day
   ---- same here for all possible durations ---
From ...

我猜 Thta 也会起作用(不过我不确定这是否可行),但我可能需要创建大约 250 列来涵盖所有可能性。这是一个安全的选择吗?

任何帮助都感激不尽

4

2 回答 2

1

我相信 group_concat 将是最好的方法,因为它的目的是聚合与特定列相关的多条数据。

但是,适应 peterm 的 SQL fiddle,如果使用用户定义的变量,这可以在 1 个查询中完成。(如果忽略设置变量的初始查询)

http://dev.mysql.com/doc/refman/5.7/en/user-variables.html

SET @productTemp := '', @increment := 0;

SElECT
  @increment := if(@productTemp != Product_id, @increment + 1, @increment) AS limiter,
  @productTemp :=Product_id as Product_id,
  Product.name,
  Price.id as Price_id,
  Price.start,
  Price.end
FROM 
  Product
LEFT JOIN
  Price ON Product.Id=Price.Product_id
WHERE 
  `start` >= '2013-05-01' AND `end` <= '2013-05-15'
GROUP BY
 Price_id
HAVING 
  limiter <=2

我们在这里所做的只是在产品 id 与遇到的最后一个不同时才增加用户定义的 var "incrementer"。

由于别名不能在 WHERE 条件中使用,我们必须按唯一 ID(在本例中为价格 ID)分组,以便我们可以使用 HAVING 减少结果。在这种情况下,我有一个完整的结果集,应该包括 3 个产品 ID,减少到只显示 2 个。

请注意:这不是我在大型数据集或生产环境中推荐的解决方案。甚至 mysql 手册也强调了用户定义的变量可能会根据优化器采用的路径而表现得有些不规律。但是,我过去曾使用它们对一些内部统计数据产生了很大的影响。

小提琴:http ://sqlfiddle.com/#!2/96c92/3

于 2013-06-07T09:43:39.093 回答
0

没有样本数据和所需的输出很难说,但你可以尝试这样的事情

SElECT p.*, q2.*
  FROM 
(
  SElECT Product_id
    FROM Price
   WHERE `start` >= '2013-05-01' AND `end` <= '2013-05-15'
   GROUP BY Product_id
  LIMIT 0,10
) q1 JOIN 
(
    SELECT *
      FROM Price
     WHERE `start` >= '2013-05-01' AND `end` <= '2013-05-15'
) q2 ON q1.Product_id = q2.Product_id JOIN product p
     ON q1.Product_id = p.Id

这是SQLFiddle演示

于 2013-06-07T09:09:07.357 回答