首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL BIT_COUNT 與 BIT_OR 位運算函數實戰:去重計數天數統計優化

     編輯:MySQL 綜合教學

MySQL BIT_COUNT 與 BIT_OR 位運算函數實戰

場景:統計不重複天數

表 t1(year, month, day) 記錄訪問日誌,同一天可能多筆記錄,需統計每月不重複天數。

原始資料

+------+-------+------+
| year | month | day  |
+------+-------+------+
| 2000 | 01    | 01   |
| 2000 | 01    | 20   |
| 2000 | 01    | 30   |
| 2000 | 02    | 02   |
| 2000 | 02    | 23   |
| 2000 | 03    | 13   |
| 2000 | 02    | 23   |  -- 重複: 2月23日出現兩次
+------+-------+------+

錯誤做法:COUNT 不去重

SELECT year, month, COUNT(day) AS days
FROM t1 GROUP BY year, month;
-- 結果: 2月統計為 3 天 (實際僅 2 天)

位運算解法:BIT_OR + BIT_COUNT

SELECT year, month, 
       BIT_COUNT(BIT_OR(1 << day)) AS days
FROM t1
GROUP BY year, month;
-- 結果: 2月正確統計為 2 天

原理深度解析

  1. 1 << day:將 1 左移 day 位,產生只有第 day 位為 1 的二進制數
    • day=2 → 100 (二進制) = 4
    • day=23 → 10000000000000000000000 = 8,388,608
  2. BIT_OR():對群組內所有值執行位元 OR 運算,合併所有「天」的位標記
    • 100 | 10000000000000000000000 | 100 = 10000000000000000000100
    • 重複的 day=2 只會設定同一個位,自動去重
  3. BIT_COUNT():計算二進制中 1 的個數,即不重複天數
    • 結果二進制有 2 個 1 → 統計為 2 天

現代簡潔寫法:COUNT(DISTINCT)

SELECT year, month, COUNT(DISTINCT day) AS days
FROM t1
GROUP BY year, month;

推薦使用:語意清晰、可讀性強、效能相當 (MySQL 5.7+ 優化器對 DISTINCT 聚合有專門優化)。

函數參考

函數說明範例
BIT_COUNT(N)回傳長整數 N 二進制中 1 的個數BIT_COUNT(29) = 4 (11101)
BIT_OR(expr)回傳群組內所有值位元 OR 結果 (64-bit 精度)BIT_OR(1|2|4) = 7
BIT_AND(expr)回傳群組內所有值位元 AND 結果BIT_AND(7|3) = 3
BIT_XOR(expr)回傳群組內所有值位元 XOR 結果BIT_XOR(1|2|3) = 0

適用場景延伸

  • 權限位掩碼統計 (如用戶擁有的權限種類數)
  • 標籤系統:統計文章覆蓋的標籤種類
  • 出席/打卡天數統計 (本文核心場景)
  • 任何「集合去重計數」且元素範圍在 0-63 之間的場景
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved