mysql如何進行累加計算

  • 2019 年 12 月 8 日
  • 筆記

01、前言

接了一個需求,產品想分析一下用戶增長的曲線。也就是某個時間段的每日總人數列表。好對近期活動進行一個效果的評測。這個統計sql還是花了我一小段時間的。mysql統計這個還是需要一定的技巧的。

02、需求分析

user_id

reg_time

1

2019-09-03

2

2019-09-04

3

2019-09-04

4

2019-09-05

5

2019-09-05

6

2019-09-06

假如上表為user_info,我們很容易根據時間維度統計出每日新增的人數。sql如下:

select reg_time, count(user_id) daily_quantityfrom user_infogroup by reg_time

通過上面的sql我們很容易得出以下列表:

reg_time

daily_quantity

2019-09-03

1

2019-09-04

2

2019-09-05

2

2019-09-06

1

但是這個並不是我們想要的結果。我們想要的應該是 上一天的總人數加上今天的凈增長數,以此類推。下面才是我們想要的結果:

reg_time

daily_quantity

2019-09-03

1

2019-09-04

3

2019-09-05

5

2019-09-06

6

這就有點棘手了,我們需要進行累加計算。我嘗試了自鏈接,函數等一些操作後還是沒有得到一個正確的結果。這時想到如果是java程式碼處理這個就再合適不過了,我們只要聲明初始值,然後循環累加就能計算出結果了:

public static void main(String[] args) {    int[] arr = {1, 2, 2, 1};    int[] ints = dailyQuantityArr(0, arr);  for (int i : ints) {    System.out.println("i = " + i);  }}public static int[] dailyQuantityArr(int base, int[] dailyIncrQuantity) {    int[] result = new int[dailyIncrQuantity.length];    // 累加填充    for (int i = 0; i < dailyIncrQuantity.length; i++) {      base += dailyIncrQuantity[i];      result[i] = base;    }    return result;}

上面的偽程式碼就可以計算出結果。當然如果可以的話盡量在java業務程式碼進行這種複雜運算。但是產品給出的需求是我們能夠提供一句sql能夠直接在可視化數據引擎中得出他要的答案。於是從上面的程式碼得出靈感。

mysql是否有這種變數呢?有!當然有。記得很普遍的場景,以前經常有業務需要我們輸出序號,Oracle是自帶一個偽列rownum,但是mysql沒有。mysql通常通過聲明自增變數來生成序號。拿user_info表舉例子:

select (@i:=@i+1) as rownum, user_idfrom user_info ,(select @i:=0) as r

03、Mysql 用戶變數

mysql 變數分為 局部變數、用戶變數、會話變數、全局變數 。上面的語句我們使用的是用戶變數。用戶變數與資料庫連接有關,在連接中聲明的變數,在存儲過程中創建了用戶變數後一直到資料庫實例接斷開的時候,變數就會消失。在此連接中聲明的變數無法在另一連接中使用。

MySQL中用戶變數不用事前申明,使用的時候以@varname的格式進行聲明。通過 := 或者 = 進行賦值操作。如果需要對外輸出需要用 select 關鍵字,而且賦值必須使用 := 符號。

04、Mysql累加計算

我們學習了用戶變數後就知道如何進行累加計算了,那麼user_info表的日累計總人數應該是這樣的:

select a.reg_time,        a.daily,        @i:=@i+a.daily as daily_quantity     from (select reg_time ,count(user_id) dailyfrom user group by reg_time ) a ,(select @i:=0) b

查詢的結果如下,符合邏輯需要。

reg_time

daily

daily_quantity

2019-09-03

1

1

2019-09-04

2

3

2019-09-05

2

5

2019-09-06

1

6

但是這裡有一個小坑,在實際業務中`@i`初始化的時候有可能不為0,比如我們統計上面9月4號到9月6號這時候之前的總人數為1 。這個要特別注意。實際業務開發中如果我們能在邏輯編碼中實現還是建議在邏輯編碼中進行一些複雜的運算。

05、總結

今天我們通過mysql用戶變數解決了一個在sql中累加計算的問題。不知道你有沒有其它好的思路呢?歡迎留言討論。