简体   繁体   English

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

[英]Get minimum price of each product for given group(s)

I have these simple tables:我有这些简单的表格:

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       |
+----+---------------+-------------+--------+------------+------------+

Logic逻辑

  • prices is a historical table. prices是一个历史表。
  • Each row represents a price record for a product and a customer group.每行代表一个产品和一个客户组的price记录。
  • endDate = NULL means price entry is valid between date and eternity (unless conditions below occur). endDate = NULL表示price输入在date和永恒之间有效(除非出现以下情况)。
  • If a price record for the same customerGroup and productCode has a newer matching date , it overrides the older ones — even if the price is higher.如果同一customerGroupproductCodeprice记录具有较新的匹配date ,则它会覆盖较旧的匹配日期——即使price更高。
  • The minimum price value for the same productCode and matching date(s) will win;相同productCode和匹配日期的最低price将获胜; as long as the customerGroup it has matches with the given group(s).只要customerGroup它与给定的组匹配。

Goal 1目标 1

To get the minimum possible price record:要获得可能的最低价格记录:

  • for a member of group BLUE and DEFAULT对于组BLUEDEFAULT的成员
  • for product P01用于产品P01
  • in date 2019-10-01日期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;

this returns the correct / expected single result:这将返回正确/预期的单个结果:

+----+---------------+-------------+--------+------------+------------+
| id | customerGroup | productCode | price  | date       | endDate    |
+----+---------------+-------------+--------+------------+------------+
|  5 | BLUE          | P01         | 1.3100 | 2019-01-01 | NULL       |
+----+---------------+-------------+--------+------------+------------+

Goal 2 (Question)目标 2(问题)

How to get the minimum possible price record for each product in products at once?如何一次获得产品中每个products的最低价格记录

The result should be:结果应该是:

+----+---------------+-------------+--------+------------+------------+
| 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       |
+----+---------------+-------------+--------+------------+------------+

Notes:笔记:

  • I'm looking for a way to do this without using GROUP_CONCAT in the outer query.我正在寻找一种在外部查询中不使用GROUP_CONCAT的方法。
  • MIN + GROUP BY usage is not a solution since that won't properly return all necessary fields such as customerGroup and date ... MIN + GROUP BY使用不是一个解决方案,因为它不会正确返回所有必要的字段,例如customerGroupdate ...

Here is a SQL Fiddle .这是SQL 小提琴

Goal 2 (Question) How to get the minimum possible price record for each product in products at once?目标2(问题)如何一次获得产品中每种产品的最低价格记录?

The answer is:答案是:

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

output: P01 0.5 P02 0.6 P03 0.7 output:P01 0.5 P02 0.6 P03 0.7

But your request result is grouping by id, so it can not display the minimum price by product.但是您的请求结果是按 id 分组的,因此无法按产品显示最低价格。 Also the actual data in the result you show is not actually the minimum price?您显示的结果中的实际数据实际上不是最低价格吗? (which is confusing). (这令人困惑)。

Query for second question查询第二个问题

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;

Correct me if I am wrong I will update the answer accordingly..如果我错了,请纠正我,我会相应地更新答案..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM