【发布时间】:2018-10-09 13:29:22
【问题描述】:
给定一个包含有关产品可用性信息的状态表,我如何选择与产品有效的最近 20 天内的第 1 天相对应的日期?
是的,我知道这个问题很难理解。我认为另一种说法是:我想知道每种产品在其活跃的过去 20 天内销售了多少次,这意味着该产品可能已经活跃多年,但我只想要销售额从最近 20 天的“活跃”状态开始计算。
这在服务器端很容易实现(即从数据库中获取任何产品集合、迭代它们、对状态表执行 n+1 查询等),但我有数十万个项目,所以这是必要的出于性能原因在 SQL 中执行此操作。
表格:产品
+-------+-----------+
| id | name |
+-------+-----------+
| 1 | Apple |
| 2 | Banana |
| 3 | Grape |
+-------+-----------+
表格:状态
+-------+-------------+---------------+---------------+
| id | name | product_id | created_at |
+-------+-------------+---------------+---------------+
| 1 | active | 1 | 2018-01-01 |
| 2 | inactive | 1 | 2018-02-01 |
| 3 | active | 1 | 2018-03-01 |
| 4 | inactive | 1 | 2018-03-15 |
| 6 | active | 1 | 2018-04-25 |
| 7 | active | 2 | 2018-03-01 |
| 8 | active | 3 | 2018-03-10 |
| 9 | inactive | 3 | 2018-03-15 |
+-------+-------------+---------------+---------------+
表:项目(订购的产品)
+-------+---------------+-------------+
| id | product_id | order_id |
+-------+---------------+-------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 1 | 4 |
| 5 | 1 | 5 |
| 6 | 2 | 3 |
| 7 | 2 | 4 |
| 8 | 2 | 5 |
| 9 | 3 | 5 |
+-------+---------------+-------------+
表格:订单
+-------+---------------+
| id | created_at |
+-------+---------------+
| 1 | 2018-01-02 |
| 2 | 2018-01-15 |
| 3 | 2018-03-02 |
| 4 | 2018-03-10 |
| 5 | 2018-03-13 |
+-------+---------------+
我希望我的最终结果如下所示:
+-------+-----------+----------------------+--------------------------------+
| id | name | recent_sales_count | date_to_start_counting_sales |
+-------+-----------+----------------------+--------------------------------+
| 1 | Apple | 3 | 2018-01-30 |
| 2 | Banana | 0 | 2018-04-09 |
| 3 | Grape | 1 | 2018-03-10 |
+-------+-----------+----------------------+--------------------------------+
这就是我所说的最近 20 天的活跃天数,例如苹果:
最后一次激活是在“2018-04-25”。那是 4 天 前。
在此之前,它自 '2018-03-15' 以来一直处于非活动状态,因此直到 '2018-04-25' 之前的所有这些天都不算在内。
在此之前,它自“2018-03-01”以来一直处于活动状态。距离“2018-03-15”还有 14 天。
在此之前,自“2018 年 2 月 1 日”以来处于非活动状态。
最后,它自 '2018-01-01' 以来一直处于活动状态,因此它应该只从 '2018- 向后计算缺少的 2 天 (4 + 14 + 2 = 20) 02-01',导致 date_to_start_counting_sales = '2018-01-30'。
有了“2018-01-30”日期,我就可以计算过去 20 天的 Apple 订单:3。
希望这是有道理的。
这是一个fiddle,上面提供了数据。
【问题讨论】:
-
您能否仔细检查您想要的结果中的
date_to_start_counting_sales(假设您使用的是 YYYY-MM-DD)?请提供一个示例,说明您对其中一种产品的“过去 20 天处于活跃状态”的含义。例如。 Apple 最后一次活跃是 '2018-04-25',所以从 '2018-04-25' 到 '2018-05-15' 的所有销售额?或者您想要存在完整 20 天间隔的最后一个活动时间?我无法从您提供的信息中追溯您如何获得所需结果的数据。 -
@krokodilko 正如我所提到的,我已经尝试用服务器端语言解决问题,但在 SQL 中完成它时遇到了问题。感谢您的精彩合作。
-
伙计,你在星期天早上让我头疼......好吧,我想再次理解这一点。你能准备一下你的结构和数据,这样我们就可以有一个操场了吗?
-
这已经是一个很大的帮助:sqlfiddle.com/#!9/b7817f/3 其余部分我仍然很难理解,但从我在这里的查询来看,这肯定是花生。我喝了杯咖啡,我完成了这个
-
plsql 仍然需要很多时间来编写,而且几乎不可能转换为 mysql ......所以我改用 mysql 。反正一直想学。希望能帮助到你。现在让我着迷于这个问题!哈