【问题标题】:MySQL count / track streaks or consecutive datesMySQL 计数/跟踪条纹或连续日期
【发布时间】:2016-11-12 18:56:32
【问题描述】:
+-----+------------+------------+---------------------+
| id  | seller_id  | prod_id    | date                |
+-----+------------+----------------------------------+
|   1 | 283        | 4243       | 2016-10-10 23:55:01 |
|   2 | 287        | 4243       | 2016-10-10 02:01:06 |
|   3 | 283        | 4243       | 2016-10-11 23:55:06 |
|   4 | 311        | 4243       | 2016-10-11 23:55:07 |
|   5 | 283        | 4243       | 2016-10-12 23:55:07 |
|   6 | 283        | 4243       | 2016-10-13 23:55:07 |
|   7 | 311        | 4243       | 2016-10-13 23:55:07 |
|   8 | 287        | 4243       | 2016-10-14 23:57:06 |
|   9 | 311        | 4243       | 2016-10-14 23:57:06 |
|  10 | 311        | 4243       | 2016-10-15 23:57:06 |
+-----+------------+------------+---------------------+

如何使用 MySQL 查询从上表中提取以下信息?

+------------+---------+----------------+---------------+
| seller_id  | prod_id | streak in days | begin streak  | 
+-----+------------+--------------------+---------------+
| 283        | 4243    | 4              | 2016-10-10    |
| 287        | 4243    | 1              | 2016-10-10    |
| 311        | 4243    | 1              | 2016-10-11    |
| 311        | 4243    | 3              | 2016-10-13    |
| 287        | 4243    | 1              | 2016-10-14    |
+------------+---------+----------------+---------------|

所以基本上我需要确定每个销售产品 (prod_id) 的卖家 (seller_id) 的每个连续日期。

我将此示例限制为 1 个 prod_id 并且只有几天的范围,但卖家确实销售了超过 1 个产品 (prod_id)

【问题讨论】:

    标签: mysql sql date


    【解决方案1】:
    SELECT
      seller_id
      ,prod_id
      ,COUNT(*) as StreakInDays
      ,MIN(DateCol) as BeginStreak
    FROM
      (
        SELECT
          seller_id
          ,prod_id
          ,DATE(DateCol) as DateCol
          ,(@rn:= if((@seller = seller_id) AND (@prod = prod_id), @rn + 1,
                     if((@seller:= seller_id) AND (@prod:= prod_id), 1, 1)
                      )
            ) as RowNumber
        FROM
          Transact t
          CROSS JOIN (SELECT @seller:=0, @prod:=0, @rn:=0) var
        ORDER BY
          seller_id
          ,prod_id
          ,DATE(DateCol)
        ) t    
    GROUP BY
      seller_id
      ,prod_id
      ,DATE_SUB(DateCol, INTERVAL RowNumber Day)
    ORDER BY
      prod_id
      ,DATE_SUB(DateCol, INTERVAL RowNumber Day)
      ,seller_id
    

    生成一个按seller_id 和prod_id 分区的分区行号。然后使用 Date - RownNumber 作为分组,您可以通过简单的聚合得到答案。

    SQL Fiddle 向您展示它适用于多种产品、卖家等。http://sqlfiddle.com/#!9/0a0c44/8/0

    请注意,如果同一卖家可能在同一天对一件产品进行超过 1 笔交易,那么您需要在生成 DISTINCT Seller_id、prod_id、DATE(date) 的派生表之前替换 Transact行号如下:

    SELECT
      seller_id
      ,prod_id
      ,COUNT(*) as StreakInDays
      ,MIN(DateCol) as BeginStreak
    FROM
      (
        SELECT
          seller_id
          ,prod_id
          ,DateCol
          ,(@rn:= if((@seller = seller_id) AND (@prod = prod_id), @rn + 1,
                     if((@seller:= seller_id) AND (@prod:= prod_id), 1, 1)
                      )
            ) as RowNumber
        FROM
         (SELECT DISTINCT seller_id, prod_id, DATE(DateCol) as DateCol
           FROM
             Transact
          )t
          CROSS JOIN (SELECT @seller:=0, @prod:=0, @rn:=0) var
        ORDER BY
          seller_id
          ,prod_id
          ,DateCol
        ) t    
    GROUP BY
      seller_id
      ,prod_id
      ,DATE_SUB(DateCol, INTERVAL RowNumber Day)
    ORDER BY
      prod_id
      ,DATE_SUB(DateCol, INTERVAL RowNumber Day)
      ,seller_id
    

    http://sqlfiddle.com/#!9/0a0c44/11

    【讨论】:

    • 谢谢!正是我想要的。我有一个小问题,虽然它弄乱了计数,即:有时在 1 天有多个条目用于某个卖家 ID / prod_id 组合。我每天只想要 1 个计数,同一天的其他条目应该被视为重复,应该被忽略。我相信“DISTINCT”应该能够实现,但我不知道该怎么做。
    • 他们第二块具有派生表的代码(SELECT DISTINCT 卖家......)应该处理这种情况。基本上,您不需要直接在表上生成行号,而是需要在派生表上执行此操作,从而消除重复项。如果我的回答对你有用,请投票并接受它,以便其他人知道你得到了你需要的东西。谢谢!
    • Matt,在 prod_id 可以使用和新的 (prod_cond) 时遇到问题。我试图通过将 prod_cond 添加到查询中的 if 语句来解决它,但这仍然无法正常工作。当有 1 个 prod_id 列出新的和 1 个已使用时,条纹会被打破。此处示例:sqlfiddle.com/#!9/9a2bd/2
    • @dean2020 我不完全确定您想通过添加 prod_cond 来做什么您是否想忽略 prod_cond 中的更改,如果是这样,请按派生表的顺序在 DateCol 之前添加 prod_cond .如果您想打破连胜记录,那么您将需要更改顺序并允许使用日期时间,但是这意味着您不会按天汇总,因此您需要使用每个组的最大和最小日期差异,所以你应该创建一个组行号来简化它。
    猜你喜欢
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多