如何增加 MySQL 中列值的出现次数

How to increment count of occurences of column value in MySQL

我有以下列名称:

increment_idother_id 是唯一的,customer_email 是重复的。当返回结果时,我想知道这封电子邮件的出现次数。

对于每一行,我想知道 customer_email 值到目前为止 出现了多少次。 created_at 字段末尾会有一个 order by 子句,我还计划添加一个 where occurrences < 2

的 where 子句

我正在查询超过 500 万行,但性能并不是 重要,因为我将 运行 这是一个关于只读副本数据库的报告生产。在我的用例中,我会为了稳健性而牺牲性能。

| customer_email | incremenet_id | other_id | created_at          | occurances <- I want this |
|----------------|---------------|----------|---------------------|---------------------------|
| joe@test.com   | 1             | 81       | 2019-11-00 00:00:00 | 1                         |
| sue@test.com   | 2             | 82       | 2019-11-00 00:01:00 | 1                         |
| bill@test.com  | 3             | 83       | 2019-11-00 00:02:00 | 1                         |
| joe@test.com   | 4             | 84       | 2019-11-00 00:03:00 | 2                         |
| mike@test.com  | 5             | 85       | 2019-11-00 00:04:00 | 1                         |
| sue@test.com   | 6             | 86       | 2019-11-00 00:05:00 | 2                         |
| joe@test.com   | 7             | 87       | 2019-11-00 00:06:00 | 3                         |

如果你是 运行 MySQL 8.0,你可以做一个 window 计数:

select 
    t.*,
    count(*) over(partition by customer_email order by created_at) occurences 
from mytable t

您不需要在查询末尾使用 order by 子句来实现此功能(但如果您想对结果进行排序,则需要一个)。

如果您需要过滤 window 计数的结果,则需要一个额外的级别,因为 window 函数不能在查询的 where 子句中使用:

select *
from (
    select 
        t.*,
        count(*) over(partition by customer_email order by created_at) occurences 
    from mytable t
) t
where occurences < 2

您可以在 MySQL 的早期版本中使用变量:

select t.*,
       (@rn := if(@ce = customer_email, @rn + 1,
                  if(@ce := customer_email, 1, 1)
                 )
       ) as occurrences
from (select t.*
      from t
      order by customer_email, created_at
     ) t cross join
     (select @ce := '', @rn := 0) params;

在 MysQL 8+ 中,我会推荐 row_number():

select t.*,
       row_number() over (partition by customer_email order by created_at) as occurrences
from t;