MySQL在按照某個字段分組、排序加序號


事情是這樣的,最近領導給了一個新的需求,要求在一張訂單表中統計每個人第一次和第二次購買的時間間隔,最后還需要按照間隔統計計數,求出中位數等數據。

  • 由於MySQL不想Oracle那般支持行號、中位數等,所以怎么在表中統計處數據成為了關鍵

訂單表結構,主要包含字段如下

  • id、訂單號、購買人id、下單時間、商品信息字段、購買人信息字段等

1.為了方便后續統計,我的想法是構建了一張中間表,只存儲一些關鍵字段,如購買人id,下單時間,訂單號,以及購買的第幾次,結構如下圖:

字段解釋:fans_id:購買人id、order_time:下單時間、tid:訂單號、series:商品系列、shop:店鋪、times:第幾次購買、sync_time:同步時間、effective:是否有效、failure_time:失效時間

2.寫了一段代碼,處理歷史訂單,把所有數據按照表中格式添加進去,方便統計,每次新訂單進來時,更新一下這個表即可。

3.統計:

-- 統計購買次數最大和最小
select max(times) from 統計表 where effective = '有效'
-- 統計最大購買次數間隔、最小間隔以及平均間隔(中位數的話,由於MySQL沒有中位數函數,所以可以利用子查詢的SQL通過程序代碼計算)
SELECT
    max(date) as max,
    min(date) as min,
    sum( date * mans ) / count( mans ) as avg
FROM
    (
    SELECT
        ifnull(datediff( a.order_time, ( SELECT order_time FROM  統計表 WHERE times = 次數1 AND effective = '有效' AND a.fans_id = fans_id ) ),0) AS date,
        a.fans_id,
        1 AS mans
    FROM
         統計表 a
    WHERE
    a.times = 次數2 AND effective = '有效'
    ) t

4.由於接收訂單后,可能狀態會變,無法確保次數准確,更新統計表中每個人的次數SQL如下:

UPDATE 
      (SELECT @rownum:=@rownum+1  as rn,id,fans_id,order_time from
            (SELECT id,fans_id,order_time  from
                  統計表 where  fans_id = 購買人 and effective = '有效'
                        ORDER BY order_time asc)   h,
             (SELECT @rownum:=0) t) t1,
            statistics_repurchase  t2
set t2.times=t1.rn where t2.id=t1.id;

5.由於需求還需要支持按照商品系列查詢,所以需要在該表基礎之上建立臨時表以作統計,滿足MySQL在按照某個字段分組、排序加序號

第一版SQL如下:

SELECT
   a.fans_id,
   a.order_time,
   a.sync_time,
   count( * ) AS times
FROM
   統計表 AS a,
   統計表 AS b
WHERE
   a.fans_id = b.fans_id
   AND a.order_time >= b.order_time
   AND a.effective = '有效'
   AND b.effective = '有效'
   AND a.series LIKE concat('%','系列','%')
   AND b.series LIKE concat('%','系列','%')
GROUP BY
   a.fans_id,
   a.id
-- 按照購買人id,按照購買時間進行排序,並標記序號,加上創建表語句如下(建表時需加索引,方便后續查找):
CREATE TABLE 臨時表名 (
       id INT PRIMARY KEY AUTO_INCREMENT,
       fans_id VARCHAR ( 32 ),
       order_time datetime,
       sync_time date,
       times INT ( 6 ),
       PRIMARY KEY ( id ),
       INDEX mid_fans_id ( fans_id ) USING BTREE,
       INDEX mid_order_time ( order_time ) USING BTREE,
       INDEX mid_times ( times ) USING BTREE,
       INDEX mid_sync_time ( sync_time ) USING BTREE
   )
   AS
   (
       SELECT
           a.fans_id,
           a.order_time,
           a.sync_time,
           count( * ) AS times
       FROM
           統計表 AS a,
           統計表 AS b
       WHERE
           a.fans_id = b.fans_id
           AND a.order_time >= b.order_time
           AND a.effective = '有效'
           AND b.effective = '有效'
           AND a.series LIKE concat('%','系列','%')
           AND b.series LIKE concat('%','系列','%')
       GROUP BY
           a.fans_id,
           a.id
       );    
-- 由於數據庫版本為5.4,所以建完臨時表不支持一條sql多次查詢,沒辦法,只能直接創建表

結果如圖:

滿足了排序,但是后來我發現有一些人是同時間下單的,以至於某些人的times是重復的,於是更新為下面的SQL

SELECT
	a.fans_id,
	a.order_time,
	a.sync_time,
        ( @i := CASE WHEN @pre_keyword = fans_id THEN @i + 1 ELSE 1 END ) AS times,
	@pre_keyword:=fans_id
FROM
	( SELECT fans_id, order_time, sync_time FROM 統計表 WHERE effective = '有效'  AND series LIKE concat('%','系列','%')  ORDER BY fans_id,order_time ) a,
	( SELECT @i := 0, @pre_keyword := '' ) AS b

這次的sql是按照時間排序后,判斷當前購買人第幾次出現,打上序號,由此滿足需求

查詢結果和上圖相同,就不附圖了哈

效率這,購買人id,下單時間需要創建索引,否則可能有些慢,測試庫中數據大概七百萬左右,總體查詢可在四秒內完成

希望這篇文章能在開發中給予您一定的幫助,新人博客主,碼齡一年,如有更好的方案,望指教!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM