对于低于8的mysql版本,sql是“ntile”的替代方案吗?

yuvru6vn  于 2021-08-01  发布在  Java
关注(0)|答案(2)|浏览(393)

我正在尝试下面的代码,它根据交易的最近性、频率和货币价值来分析和评分客户。

  1. select customer_id, rfm_recency, rfm_frequency, rfm_monetary
  2. from
  3. (
  4. select customer_id,
  5. ntile(4) over (order by last_order_date) as rfm_recency,
  6. ntile(4) over (order by count_order) as rfm_frequency,
  7. ntile(4) over (order by sum_amount) as rfm_monetary
  8. from
  9. (
  10. select customer_id,
  11. max(local_date) as last_order_date,
  12. count(*) as count_order,
  13. sum(amount) as sum_amount
  14. from transaction
  15. group by customer_id) as T
  16. ) as P

然而 ntile 在mysql版本(v5)中不可用,因为它显然是一个“窗口函数”,只在v8+上工作。
我找不到替代这个功能的工作方法。我对sql非常陌生,所以我自己也很难弄清楚。
有没有 ntile 我能用的替代品?如果我删除 ntile 段。

2admgd59

2admgd591#

如果你需要MySQL8.0的特性,你真的应该升级到MySQL8.0。它们一定会更容易、更优化。
我找到了一种方法来模拟文档中显示的ntile查询:

  1. SELECT
  2. val,
  3. ROW_NUMBER() OVER w AS 'row_number',
  4. NTILE(2) OVER w AS 'ntile2',
  5. NTILE(4) OVER w AS 'ntile4'
  6. FROM numbers
  7. WINDOW w AS (ORDER BY val);

这里有一个解决方案:

  1. SELECT val, @r:=@r+1 AS rownum,
  2. FLOOR((@r-1)*2/9)+1 AS ntile2,
  3. FLOOR((@r-1)*4/9)+1 AS ntile4
  4. FROM (SELECT @r:=0,@n:=0) AS _init, numbers

2和4因子分别用于第(2)个和第(4)个变量。9的值是因为这个示例表中有9行。在运行此查询之前,必须知道表的计数。这个解决方案还需要用户定义的变量,这总是有点棘手。
结果:

  1. +------+--------+--------+--------+
  2. | val | rownum | ntile2 | ntile4 |
  3. +------+--------+--------+--------+
  4. | 1 | 1 | 1 | 1 |
  5. | 1 | 2 | 1 | 1 |
  6. | 2 | 3 | 1 | 1 |
  7. | 3 | 4 | 1 | 2 |
  8. | 3 | 5 | 1 | 2 |
  9. | 3 | 6 | 2 | 3 |
  10. | 4 | 7 | 2 | 3 |
  11. | 4 | 8 | 2 | 4 |
  12. | 5 | 9 | 2 | 4 |
  13. +------+--------+--------+--------+

我将把它作为一个练习留给您,让您根据查询和表调整此技术,或者决定是时候升级到mysql 8.0了。

展开查看全部
n3schb8v

n3schb8v2#

您可以枚举行并使用算术。不幸的是,您需要这样做三次:

  1. select floor(seqnum * 4 / @rn) as ntile_recency, t.*
  2. from (select (@rn := @rn + 1) as seqnum, t.*
  3. from (select customer_id, max(local_date) as last_order_date, count(*) as count_order,
  4. sum(amount) as sum_amount
  5. from transaction
  6. group by customer_id
  7. order by last_order_date
  8. ) t cross join
  9. (select @rn := 0) params
  10. ) t;

相关问题