获取给定组的每种产品的最低价格

时间:2019-11-08 17:03:16

标签: mysql sql join select

我有这些简单的表:

products

+----+------+---------+
| id | code | details |
+----+------+---------+
|  1 | P01  | ...     |
|  2 | P02  | ...     |
|  3 | P03  | ...     |
+----+------+---------+

prices

+----+---------------+-------------+--------+------------+------------+
| id | customerGroup | productCode | price  | date       | endDate    |
+----+---------------+-------------+--------+------------+------------+
|  1 | DEFAULT       | P01         | 1.2500 | 2018-01-01 | NULL       |
|  2 | DEFAULT       | P02         | 1.4000 | 2018-01-01 | NULL       |
|  3 | DEFAULT       | P03         | 2.0000 | 2018-01-01 | NULL       |
|  4 | DEFAULT       | P01         | 1.3000 | 2018-07-01 | NULL       |
|  5 | BLUE          | P01         | 1.3100 | 2019-01-01 | NULL       |
|  6 | BLUE          | P02         | 0.9000 | 2019-01-01 | 2019-05-01 |
|  7 | BLUE          | P03         | 2.0000 | 2019-09-01 | NULL       |
|  8 | DEFAULT       | P01         | 1.3200 | 2019-10-01 | NULL       |
|  9 | GREEN         | P01         | 0.5000 | 2019-10-01 | NULL       |
| 10 | GREEN         | P02         | 0.6000 | 2019-10-01 | NULL       |
| 11 | GREEN         | P03         | 0.7000 | 2019-10-01 | NULL       |
+----+---------------+-------------+--------+------------+------------+

逻辑

  • prices是一个历史表格。
  • 每一行代表产品和客户群的price记录。
  • endDate = NULL表示price条目在date和永恒之间有效(除非出现以下情况)。
  • 如果同一pricecustomerGroup的{​​{1}}记录具有新的 matching productCode,则它会覆盖较旧的记录-即使date更高。
  • 相同price和匹配日期的最低price值将获胜;只要productCode与指定的组都匹配。

目标1

获取最低价格记录:

  • 对于customerGroupBLUE组的成员
  • 对于产品DEFAULT
  • 日期P01
2019-10-01

这将返回正确/预期的单个结果:

SELECT
    pp.*
FROM prices AS pp
JOIN (
    SELECT customerGroup, MAX(date) AS maxDate
    FROM prices AS pp
    WHERE productCode = 'P01'
    GROUP BY customerGroup
) AS eachRow ON (pp.customerGroup = eachRow.customerGroup AND pp.date = eachRow.maxDate)
WHERE 
    pp.productCode = 'P01'
    AND FIND_IN_SET(pp.customerGroup, 'DEFAULT,BLUE') > 0
    AND ((pp.endDate IS NULL AND '2019-10-01' >= pp.date) OR (pp.endDate IS NOT NULL AND ('2019-10-01' BETWEEN pp.date AND pp.endDate)))
GROUP BY pp.customerGroup
ORDER BY pp.price ASC
LIMIT 1;

目标2(问题)

如何一次获取+----+---------------+-------------+--------+------------+------------+ | id | customerGroup | productCode | price | date | endDate | +----+---------------+-------------+--------+------------+------------+ | 5 | BLUE | P01 | 1.3100 | 2019-01-01 | NULL | +----+---------------+-------------+--------+------------+------------+ 中每种产品的最低价格记录

结果应为:

products

注意:

  • 我正在寻找一种无需在外部查询中使用+----+---------------+-------------+--------+------------+------------+ | id | customerGroup | productCode | price | date | endDate | +----+---------------+-------------+--------+------------+------------+ | 2 | DEFAULT | P02 | 1.4000 | 2018-01-01 | NULL | | 5 | BLUE | P01 | 1.3100 | 2019-01-01 | NULL | | 7 | BLUE | P03 | 2.0000 | 2019-09-01 | NULL | +----+---------------+-------------+--------+------------+------------+ 的方法。
  • GROUP_CONCAT + MIN的使用不是解决方案,因为它不能正确返回所有必需的字段,例如GROUP BYcustomerGroup ...

这里是SQL Fiddle

2 个答案:

答案 0 :(得分:0)

目标2(问题) 如何一次获得产品中每种产品的最低价格记录?

答案是:

Select p.productcode, min(p.price)
from prices p
left join products prd on p.productcode = prd.code
Group by p.productcode

输出: P01 0.5 P02 0.6 P03 0.7

但是您的请求结果是按ID分组的,因此无法按产品显示最低价格。另外,您显示的结果中的实际数据实际上不是最低价格吗? (这很令人困惑)。

答案 1 :(得分:0)

查询第二个问题

SELECT MAX(pp.customerGroup) as CustomerGroup, MAX(pp.ProductCode) as ProductCode , MIN(pp.price) as Price FROM Prices as pp
INNER JOIN Products as pro
on pp.PRoductCode = pro.Code

GROUP BY pp.customerGroup
ORDER BY pp.customerGroup;

纠正我,如果我错了,我将相应地更新答案。