MySQL中按周統計數據

2020-12-27 程序猿集錦

關注我《程序猿集錦》,獲取主頁更多分享。

背景

今天算法的同事過來問我MySQL中是否可以根據周的維度去統計某個指標?比如按周統計訂單的數量。因為數據量比較大,如果直接全部查詢到內存中去統計可能比較慢。所以他系統能夠在SQL層面先做一次聚合統計,維度是按照周去統計。

剛聽到這個需求,我有點蒙。按照周的方式去統計?MySQL中估計沒有這樣的by week的函數。有按照天統計簡單,按照月統計也簡單,我們只要把日期截取一下轉為YYYY-MM的字符串然後再分組聚合就可以了。但是他要按照周來統計,確實有點難度。

但是MySQL這麼成熟的資料庫軟體了,也不能說實現不了吧。說幹就幹,開整。

環境準備

準備建表語句

使用中使用到的表結構如和建表語句如下:

CREATE TABLE `test` (`id` int(11) NOT NULL AUTO_INCREMENT,`order_no` varchar(32) DEFAULT NULL,`create_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

初始化數據語句

測試使用到的初始化數據使用如下的SQL進行初始化:

/*如下SQL執行多次即可產生多條測試數據*/insertinto test(order_no, create_timestamp)value(substr(rand(),3,18),date_add(date_add(date_add(date_add(now(),interval floor(1+rand()*23)hour),interval floor(1+rand()*60)minute),interval floor(1+rand()*60)second),interval-floor(1+rand()*40)day));/*查看表中的數據*/select*from test;

最後的實驗環境

我們的實驗環境如下所示,要求按周統計出訂單的數目。

思路分析

MySQL中沒有自帶的把一個日期給轉換為周的函數。不過,我們可以採用曲線救國的方式來實現。雖然它沒有直接的函數,但是它自帶的日期類型的函數還是很多的。

思路:我們的目的是把每一個訂單創建時間這個欄位的值,設置為一個可以使用的group by的key。這個key要求是根據同一個周的訂單使用同一個時間。所以,我們需要想辦法把屬於同一個周的訂單的創建時間轉換為一個相同的日期,比如把所有屬於同一個周的所有訂單的創建時間,都轉換為每周的周一這個時間。這樣就可以根據周去聚合統計訂單的數目了。

在把所有訂單的創建時間轉換為這個訂單所屬的周的周一時,就要知道這個訂單的創建時間,距離這個周的一查幾天,這樣在這個訂單的創建時間這個值上減去這個天數,就可以得到周一這個時間。

MySQL中有一個函數叫做weekday(x),其中x就是傳入的一個日期類型的數據,傳入後,返回這個日期是屬於一周當中的第幾天。是一個整形的數據,值的範圍是[0,6],兩個邊界值分別代表每周的周一和周日。

一周有七天,當我們傳入一個周一的日期給weekday(x)函數的時候,它會返回一個整形的數字0;當我們傳入一個周日的日期的時候,它會返回一個整形的數字6。示例如下:

基於上面的函數weekday(x),我們可以得到每一個訂單創建的時間屬於一周當中的第幾天。SQL語句如下所示:

select*, weekday(create_timestamp)as weekdayfrom test limit10;

實驗結果如下所示:

然後我們在基於這個得到的整形的周幾,用日期相加函數data_add()把每一個訂單創建時間改為每一周的周一。使用如下的SQL語句來實現:

select*,weekday(create_timestamp)as weekday,date_add(create_timestamp,interval-(weekday(create_timestamp))day)as mondayfrom test limit10;

結果截圖如下:

此時我們已經得到每個訂單創建時間所對應的周一這個日期,但是在monday這一列中還有時分秒,這將會影響我們進行聚合的時候作為key來使用這個欄位,所以,我們需要把時分秒去掉只保留年月日即可,採用date_format(x,'%Y-%m-%d')函數就可以對這個日期進行格式化成我們希望要的格式。SQL語句如下:

select *,weekday(create_timestamp) as weekday,date_format(date_add(create_timestamp, interval - (weekday(create_timestamp) + 1) day),'%Y-%m-%d') as mondayfrom test;

結果如下圖所示:

最後,我們就可以使用聚合函數進行統計每周的訂單數了,SQL語句如下:

select monday, count(1) from (select *, weekday(create_timestamp) as weekday, date_format(date_add(create_timestamp, interval - (weekday(create_timestamp) + 1) day),'%Y-%m-%d') as monday from test) as xgroup by mondayorder by monday;

最後的統計結果如下圖所示,這就是我們希望要的結果了。

總結

最後梳理一下思路:根據每一行的創建時間計算出這個時間屬於對應周第幾天,然後用這個創建時間再減去這個的得到的第幾天,就可以把每一個創建時間轉換為每周的周一。這樣就可以把所有屬於同一個周的訂單的創建時間,轉換為了每一個周的周一。最後基於這個每周的周一就可以統計得到最後的每周的訂單數目。

在MySQL中,按周的統計雖然不能直接實現,但是我們可以根據它現有個各種日期類型的函數,稍微轉換變通一下,就可以實現我們平時的需求。所以,在遇到類似的這樣的需求的時候,不要著急,按部就班分析一下,就可以基於現有的函數慢慢的一步步實現最後希望達到的效果。

這個解題的思路不僅僅可以適用於MySQL資料庫,向Oracle資料庫、SQLserver資料庫、postgresql資料庫都可以根據這個思路來實現按周去統計數據。

相關焦點

  • 在MySQL中使用XML數據—數據格式化
    在這個例子中,使用Prepared Statement的好處是可以設置標題,然後連接到我們的查詢字符串中。 客戶端包括了比--xml選項更多的信息,但它卻是按每一行、欄位名和值的方式輸出的,MySqlDump將表結構和表數據單獨輸出。
  • MySQL mysqldump 數據導出詳解
    ,而mysqldump是導出數據過程中使用非常頻繁的一個工具;它自帶的功能參數非常多,文章中會列舉出一些常用的操作,在文章末尾會將所有的參數詳細說明列出來。--host=h1 -uroot -proot --databases db1 |mysql --host=h2 -uroot -proot db2將h1伺服器中的db1資料庫的所有數據導入到h2中的db2資料庫中,db2的資料庫必須存在否則會報錯mysqldump --host=192.168.80.137 -uroot -proot -C --databases test
  • MySQL--SQL的數據類型
    MySQL中定義數據欄位的類型對資料庫優化非常重要,前面介紹過Python的數據類型有6種,包含數字、字符串、列表、元組、集合、字典
  • MySQL中「詭異」的TIMESTAMP數據類型
    TIMESTAMP數據類型打交道,有時候TIMESTAMP類型看起來莫名其妙,測試環境都測試OK了上了預發就直接報錯了;有時候TIMESTAMP類型看起來又很詭異,表中的真實數據跟開發人員提交的表結構又南轅北轍並非所需要的;本篇文章將抽絲剝繭帶你重新認識一下這個熟悉又陌生的TIMESTAMP類型。
  • mysql查詢——mysql中數據累加的方法
    下圖是一張3月份的銷售數據表(sales),其中包含欄位序號Id、日期Date、銷量Sales,現在需要編寫一個查詢語句,統計3月1日到每日的累計銷量。方法一:通過自定義變量實現select date,sales,@cum_sales:=@cum_sales+sales as cum_salesfrom sales,(select @cum_sales:=0)corder by date asc;方法二:通過將聚合函數sum作為窗口函數實現(mysql8.0及以上版本可用
  • mysql field json MySQL JSON 類型數據操作
    美麗"');-- 獲取map中某個key值,根據map中的值做為條件select obj->>'$."漫畫"' manhua,arr from test where obj->>'$."
  • MySQL 備份數據那點事
    mysqldump什麼是 mysqldump ?mysqldump 是 MySQL 用於執行邏輯備份的一款工具,可以根據原始資料庫對象以及表的定義和數據來生成一系列可以被執行的 SQL 語句。通常我們用它作為備份或者遷移數據。
  • MySQL導出數據為csv的方法
    將資料庫中的數據導出成csv格式的文件CSV格式,其要點包括:(1)欄位之間以逗號分隔,數據行之間以\r\n分隔;
  • 從零開始學 MySQL -- 創建資料庫並插入數據
    介紹 MySQL 新建資料庫,新建表,插入數據以及基本數據類型的相關知識。在 Linux 環境裡創建一個名為 mysql_shiyan 的資料庫。在資料庫創建兩張表 employee 和 department,分別表示員工表和部門表。
  • Mysql數據誤刪除快速回滾
    作者 | Video++極鏈科技OPSTeam整理 | 包包在資料庫操作中,難免會因為各種各樣的原因對數據造成損壞,這個時候就需要對資料庫快速恢復。傳統的方法會先恢復mysql備份,再去用mysqlbinlog抽取指定時間點的日誌,再恢復,這樣的操作比較耗時,容易出錯,那有沒有一種工具可以快速把誤刪除的操作SQL逆過來,然後重新插入誤刪除的數據呢?
  • mysql安裝圖解 mysql圖文安裝教程
    填上安裝目錄,我的是「F:\Server\MySQL\MySQL Server 5.0」,也建議不要放在與作業系統同一分區,這樣可以防止系統備份還原的時候,數據被清空。按「OK」繼續。返回剛才的界面,按「Next」繼續確認一下先前的設置,如果有誤,按「Back」返回重做。按「Install」開始安裝。
  • MySQL 找出表中差異數據
    最近在工作中做資料庫部署,遇到很多奇奇怪怪的問題,導致數據表數據出現了許多問題。在數據遷移中,我們經常需要比較兩個表,以便在一個表中標誌另一個表中沒有相應記錄的記錄。例如,我們有一個新的資料庫,其架構與舊資料庫不同。
  • 【用binlog日誌】恢復 MySQL 資料庫刪除數據
    在數據丟失的緊急情況下,可以嘗試用binlog日誌功能進行數據恢復操作。正是由於binlog日誌以上的特性,在實際的案件取證中也可以通過binlog日誌來恢復刪除數據。要通過binlog日誌恢復mysql資料庫刪除數據的前提:binlog日誌確定是開啟的。
  • MySQL 數據校驗工具-愛可生
    概述  pt-table-checksum 是 Percona-Toolkit 的組件之一,用於檢測 MySQL 主、從庫的數據是否一致。其原理是在主庫執行基於 statement 的 SQL 語句來生成主庫數據塊的checksum,把相同的 SQL 語句傳遞到從庫執行,並在從庫上計算相同數據塊的 checksum,最後,比較主從庫上相同數據塊的 checksum 值,由此判斷主從數據是否一致。它能在非常大的表上工作的一個原因是,它把每個表分成行塊,並檢查每個塊與單個替換。選擇查詢。它改變塊的大小,使校驗和查詢在所需的時間內運行。
  • 將mysql數據導入access資料庫
    首頁 > 語言 > 關鍵詞 > 最新資訊 > 正文 將mysql數據導入access資料庫
  • 解密TenDB(MySQL) Flashback 實現(二):按記錄回滾實現
    庫表級閃回與記錄級閃回mysqlbinlog 庫表級 flashback 特性由同事 王翔 引入並實現。庫表級 flashback 實現:借鑑MariaDB Flashback實現思路,我們在TenDB3(MySQL 5.7)版本中實現了Flashback。
  • mysql中count(*)是最慢的嗎?
    會經常使用count函數進行數據行數統計,來滿足我們的業務需求,如電商系統中,總的用戶人數,某個用戶總的下單數等。count如何實現的:在mysql中,當數據表數據比較少的時候,使用count可以很快進行返回需要統計的數據行數,當數量比較大的時候,count的返回結果的速度就變慢的很多,出現這種情況時,使用的mysql存儲引擎大概率是InnoDB。因為在MyISAM引擎中,對每個表的總行數都會進行記錄,並存在磁碟上。
  • MySQL中如何使用流式查詢避免數據量過大導致OOM?
    其實在 MySQL 中提供了流式查詢,這允許把符合條件的數據一部分一部分的加載到內存,本 Chat 就來具體講解如何在 MySQL中使用流式查詢:使用流式查詢前,我們是如何在 MySQL 中進行查詢數據的,整個過程發生了什麼?如何使用 JDBC 編程方式在 MySQL 中使用流式查詢?
  • MySqlODBC進行MYsql和MSsql7的數據轉換
    使用MySql ODBC後就比較好辦,可以使用MSSQL7的管理工具,也可以使用mysql的管理工具,更可以使用其它方的管理工具 這裡介紹一個使用SQL7的MMC的方法 ,將MSsql7的數據轉化為Mysql的資料庫,將源和目的反之,就可以將Mysql的資料庫轉化為Mssql7的資料庫。
  • mysql大表中count()的用法以及mysql中count()的優化
    本篇文章給大家帶來的內容是關於mysql大表中count()的用法以及mysql中count()的優化,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。一個單表中包含有6000w+的數據,然而你又不能拆分.需要分別統計表中有多少數據,A產品有多少,B產品有多少這幾個數據.