SQL SERVER中位數

有11家門店數據,要求每天所有門店的各個指標的中位數

1.第一種做法,使用PERCENTILE_CONT() 函數 SQL SERVER 2012 版本及以上

PERCENTILE_CONT 函數簡介

PERCENTILE_CONT 是 SQL 中的窗口函數,用于計算連續百分位數(基于線性插值)。適用于需要獲取數據分布中特定百分位值的場景,如統計工資的中位數或 90% 分位數。

語法結構

PERCENTILE_CONT(percentile) WITHIN GROUP (ORDER BY sort_expression)
OVER ([PARTITION BY partition_expression])

  • percentile:介于 0 和 1 之間的數值,指定所需的百分位(如 0.5 表示中位數)。
  • sort_expression:用于排序的列或表達式。
  • PARTITION BY:可選,按指定列分組計算百分位數。

基礎用法示例

計算整個表中工資列的中位數(50% 分位數):

SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS median_salary
FROM employees;

分組計算示例

按部門分組計算工資的 75% 分位數:

SELECT department_id,PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY salary) AS percentile_75
FROM employees
GROUP BY department_id;

窗口函數用法

結合 OVER 和 PARTITION BY 計算每個部門的工資中位數:

SELECT employee_id,department_id,salary,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) OVER (PARTITION BY department_id) AS dept_median_salary
FROM employees;

多百分位計算

單次查詢中計算多個百分位值:

SELECT PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY salary) AS percentile_25,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS percentile_50,PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY salary) AS percentile_75
FROM employees;

注意事項

  1. PERCENTILE_CONT 在 Oracle、PostgreSQL 和 SQL Server 中支持,但 MySQL 需使用 PERCENTILE_CONT 的替代方案。
  2. 結果為浮點數,即使輸入是整數類型。
  3. 空值(NULL)會被自動忽略。
  4. 與 PERCENTILE_DISC 的區別:PERCENTILE_CONT 返回插值結果,PERCENTILE_DISC 返回實際存在的值。

解決代碼:

WITH test_basedata AS (-- 模擬11家門店的指標數據(sdate統一為20250814,覆蓋不同指標值,方便驗證中位數)SELECT '20250814' AS sdate, 'SH001' AS shopid, 0.25 AS profit_rate, 89.5 AS avg_customer_price, 2.1 AS avg_num_purchases, 0.85 AS salevalue_finishrate, 0.12 AS abysku_rate, 35 AS dsiUNION ALL SELECT '20250814', 'SH002', 0.32, 105.2, 1.8, 1.02, 0.08, 28UNION ALL SELECT '20250814', 'SH003', 0.18, 76.9, 2.5, 0.68, 0.15, 42UNION ALL SELECT '20250814', 'SH004', 0.41, 120.7, 1.5, 1.25, 0.05, 22UNION ALL SELECT '20250814', 'SH005', 0.29, 98.3, 2.3, 0.95, 0.10, 30UNION ALL SELECT '20250814', 'SH006', 0.35, 112.1, 1.9, 1.10, 0.07, 25UNION ALL SELECT '20250814', 'SH007', 0.22, 82.4, 2.4, 0.75, 0.13, 38UNION ALL SELECT '20250814', 'SH008', 0.38, 109.6, 1.7, 1.08, 0.06, 26UNION ALL SELECT '20250814', 'SH009', 0.27, 92.8, 2.2, 0.88, 0.11, 33UNION ALL SELECT '20250814', 'SH010', 0.31, 10.5, 2.0, 0.99, 0.09, 29UNION ALL SELECT '20250814', 'SH011', 0.42, 10.5, 2.0, 0.99, 0.09, 29
),
daily_medians AS (SELECTdistinct sdate,-- 計算中位數PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY profit_rate) OVER(PARTITION BY sdate) AS median_profit_rate,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY avg_customer_price) OVER(PARTITION BY sdate) AS median_avg_customer_price,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY avg_num_purchases) OVER(PARTITION BY sdate) AS median_avg_num_purchases,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salevalue_finishrate) OVER(PARTITION BY sdate) AS median_salevalue_finishrate,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY abysku_rate) OVER(PARTITION BY sdate) AS median_abysku_rate,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY dsi) OVER(PARTITION BY sdate) AS median_dsiFROM test_basedata -- GROUP BY sdate,profit_rate,avg_customer_price,avg_num_purchases,salevalue_finishrate,abysku_rate,dsi
)
SELECT * FROM daily_medians;

2.第二種做法,通用版本

解決代碼:

1.首先利用窗口函數,求出總行數以及每個指標的排序

2.再利用ceiling 向上取整函數,和floor 向下取整函數 去求中位數的位置,并且返回對應的中位數數值

3.最后兩數加和,取平均值

代碼功能說明

這段SQL代碼用于計算多個門店在不同業務指標上的中位數值。通過創建臨時測試數據表test_basedata,模擬了11家門店在利潤、客單價、購買次數等指標上的數據,并采用窗口函數等方法計算各指標的中位數。

數據結構說明

臨時表test_basedata包含以下字段:

  • sdate:日期標識(固定為20250814)
  • shopid:門店編號
  • profit_rate:利潤率
  • avg_customer_price:客單價
  • avg_num_purchases:平均購買次數
  • salevalue_finishrate:銷售目標完成率
  • abysku_rate:缺貨率
  • dsi:庫存周轉天數

核心計算邏輯

中位數計算原理: 當數據量為奇數時取中間值,偶數時取中間兩個值的平均數。代碼通過CEILINGFLOOR函數分別定位中間位置的上下界。

計算過程分解

  1. 內層查詢使用ROW_NUMBER()為每個指標按值排序并標記排名
  2. 中間層查詢通過MAX(CASE WHEN...)提取中間位置對應的指標值
  3. 外層查詢對偶數的中間位置取平均值得到最終中位數

關鍵函數說明

  • ROW_NUMBER() OVER (PARTITION BY...ORDER BY...)
    窗口函數,對分組后的數據按指定字段排序并生成序號

  • CEILING(total_count/2.0)
    向上取整,用于定位中位數上界位置(如10個值時返回5,11返回6(5.5向上取整為6))

  • FLOOR(total_count/2.0)+1
    向下取整后+1,用于定位中位數下界位置(如10個值時返回6,11返回6(5.5向下取整為5,5+1=6))

  • COUNT(*) OVER (PARTITION BY sdate)
    計算每個日期的總記錄數,用于判斷奇偶性

結果輸出說明

最終輸出包含:

  • 原始日期字段sdate
  • median_profit_rate:利潤率中位數
  • median_avg_customer_price:客單價中位數
  • median_avg_num_purchases:平均購買次數中位數
  • median_salevalue_finishrate:銷售完成率中位數
  • median_abysku_rate:缺貨率中位數
  • median_dsi:庫存周轉天數中位數

特殊處理說明

對于偶數個數據點(如示例中的11條記錄):

  • 利潤率中位數 = (第6名的值 + 第6名的值)/2
  • 實際會取相同值,等同于直接取第6名的值

對于奇數個數據點(如10條記錄):

  • 會正確計算第5名和第6名指標值的平均數

解決代碼:


WITH test_basedata AS (-- 模擬10家門店的指標數據(sdate統一為20250814,覆蓋不同指標值,方便驗證中位數)SELECT '20250814' AS sdate, 'SH001' AS shopid, 0.25 AS profit_rate, 89.5 AS avg_customer_price, 2.1 AS avg_num_purchases, 0.85 AS salevalue_finishrate, 0.12 AS abysku_rate, 35 AS dsiUNION ALL SELECT '20250814', 'SH002', 0.32, 105.2, 1.8, 1.02, 0.08, 28UNION ALL SELECT '20250814', 'SH003', 0.18, 76.9, 2.5, 0.68, 0.15, 42UNION ALL SELECT '20250814', 'SH004', 0.41, 120.7, 1.5, 1.25, 0.05, 22UNION ALL SELECT '20250814', 'SH005', 0.29, 98.3, 2.3, 0.95, 0.10, 30UNION ALL SELECT '20250814', 'SH006', 0.35, 112.1, 1.9, 1.10, 0.07, 25UNION ALL SELECT '20250814', 'SH007', 0.22, 82.4, 2.4, 0.75, 0.13, 38UNION ALL SELECT '20250814', 'SH008', 0.38, 109.6, 1.7, 1.08, 0.06, 26UNION ALL SELECT '20250814', 'SH009', 0.27, 92.8, 2.2, 0.88, 0.11, 33UNION ALL SELECT '20250814', 'SH010', 0.31, 10.5, 2.0, 0.99, 0.09, 29UNION ALL SELECT '20250814', 'SH011', 0.42, 10.5, 2.0, 0.99, 0.09, 29
)
SELECT sdate,-- 計算中位數(偶數時取平均值)(median_profit_rate_high + median_profit_rate_low) / 2.0 AS median_profit_rate,(median_avg_customer_price_high + median_avg_customer_price_low) / 2.0 AS median_avg_customer_price,(median_avg_num_purchases_high + median_avg_num_purchases_low) / 2.0 AS median_avg_num_purchases,(median_salevalue_finishrate_high + median_salevalue_finishrate_low) / 2.0 AS median_salevalue_finishrate,(median_abysku_rate_high + median_abysku_rate_low) / 2.0 AS median_abysku_rate,(median_dsi_high + median_dsi_low) / 2.0 AS median_dsi
FROM (SELECT sdate,MAX(CASE WHEN profit_rate_rank = CEILING(total_count/2.0) THEN profit_rate END) AS median_profit_rate_high,MAX(CASE WHEN profit_rate_rank = FLOOR(total_count/2.0)+1 THEN profit_rate END) AS median_profit_rate_low,MAX(CASE WHEN avg_customer_price_rank = CEILING(total_count/2.0) THEN avg_customer_price END) AS median_avg_customer_price_high,MAX(CASE WHEN avg_customer_price_rank = FLOOR(total_count/2.0)+1 THEN avg_customer_price END) AS median_avg_customer_price_low,MAX(CASE WHEN avg_num_purchases_rank = CEILING(total_count/2.0) THEN avg_num_purchases END) AS median_avg_num_purchases_high,MAX(CASE WHEN avg_num_purchases_rank = FLOOR(total_count/2.0)+1 THEN avg_num_purchases END) AS median_avg_num_purchases_low,MAX(CASE WHEN salevalue_finishrate_rank = CEILING(total_count/2.0) THEN salevalue_finishrate END) AS median_salevalue_finishrate_high,MAX(CASE WHEN salevalue_finishrate_rank = FLOOR(total_count/2.0)+1 THEN salevalue_finishrate END) AS median_salevalue_finishrate_low,MAX(CASE WHEN abysku_rate_rank = CEILING(total_count/2.0) THEN abysku_rate END) AS median_abysku_rate_high,MAX(CASE WHEN abysku_rate_rank = FLOOR(total_count/2.0)+1 THEN abysku_rate END) AS median_abysku_rate_low,MAX(CASE WHEN dsi_rank = CEILING(total_count/2.0) THEN dsi END) AS median_dsi_high,MAX(CASE WHEN dsi_rank = FLOOR(total_count/2.0)+1 THEN dsi END) AS median_dsi_low,total_countFROM (SELECT sdate,profit_rate,avg_customer_price,avg_num_purchases,salevalue_finishrate,abysku_rate,dsi,ROW_NUMBER() OVER (PARTITION BY sdate ORDER BY profit_rate) AS profit_rate_rank,COUNT(*) OVER (PARTITION BY sdate) AS total_count,ROW_NUMBER() OVER (PARTITION BY sdate ORDER BY avg_customer_price) AS avg_customer_price_rank,ROW_NUMBER() OVER (PARTITION BY sdate ORDER BY avg_num_purchases) AS avg_num_purchases_rank,ROW_NUMBER() OVER (PARTITION BY sdate ORDER BY salevalue_finishrate) AS salevalue_finishrate_rank,ROW_NUMBER() OVER (PARTITION BY sdate ORDER BY abysku_rate) AS abysku_rate_rank,ROW_NUMBER() OVER (PARTITION BY sdate ORDER BY dsi) AS dsi_rankFROM test_basedata) ranked_dataGROUP BY sdate, total_count
)  median_calculation

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/93893.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/93893.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/93893.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【java中springboot引入geotool】

學習目標: 在Spring Boot項目中引入GeoTools庫,可以按照以下步驟進行:理解GeoTools庫的基本信息和用途 GeoTools是一個開源的Java庫,用于處理地理信息系統(GIS)數據。它提供了對空間數據的讀取、寫入、查詢…

多項目開發環境:如何使用update-alternatives管理多版本Java JDK?(Windows、Mac、Ubuntu)

如何使用update-alternatives管理多版本Java JDK?(Windows、Mac、Ubuntu) 📖 摘要 在實際開發中,往往會遇到既要維護老項目又要跟進新特性的場景,這就需要在一臺機器上同時安裝并切換多個Java JDK版本。本…

力扣57:插入區間

力扣57:插入區間題目思路代碼題目 給你一個 無重疊的 ,按照區間起始端點排序的區間列表 intervals,其中 intervals[i] [starti, endi] 表示第 i 個區間的開始和結束,并且 intervals 按照 starti 升序排列。同樣給定一個區間 newInterval […

KVM虛擬化技術解析:從企業應用到個人創新的開源力量

1 .KVM:開源虛擬化的核心引擎 KVM(Kernel-based Virtual Machine)作為Linux內核原生集成的開源虛擬化模塊,徹底改變了現代數據中心的虛擬化格局。它通過將Linux內核轉變為Type-1型虛擬機監控器(Hypervisor)…

28.Linux :通過源代碼編譯安裝lamp

Linux :通過源代碼編譯安裝lamp 區別特性源代碼編譯安裝yum 安裝安裝方式從源代碼編譯構建預編譯的二進制包自定義程度高度可定制有限定制性能優化可針對特定硬件優化通用優化依賴管理手動解決依賴關系自動解決依賴安裝復雜度復雜,需技術經驗簡單&#x…

應用控制技術

一、 應用特征識別技術1.傳統行為檢測技術1.1 五元組檢測原理1.2 配置思路1.3 效果展示需求背景21.4 傳統行為檢測的缺陷無法識別應用層內容:若應用更換端口(如QQ改用隨機端口)或偽裝協議(如HTTPS加密),傳統…

當MySQL的int不夠用了

關于int的長度很多時候看到int(8)這樣的定義,其實這是工具導出的不專業。int是范圍,不是長度。在開發有了共識(知道這個長度不算數,要看范圍)以后,上來就是所有的類型都是bigint。int的范圍int的取值范圍是…

讓AI學會“邊做邊想“:ReAct的實戰指南

小智的求職困境有個叫小智的AI助手,它剛從"大語言模型大學"畢業,滿懷信心地去應聘一家咨詢公司的智能助理職位。面試官問:"北京和上海哪個城市人口更多?"小智立刻回答:"根據我的知識&#xf…

vue優化有哪些手段?

vue本身存在的方法 v-if 和v-show 的合理運用,頻繁使用的組件使用v-show,不頻繁的使用v-if,來減少dom的渲染路由懶加載 采用()>import(index.vue)當路由被訪問的時候才回去加載使用keep-alive緩存頁面,減少沒必要的重復渲染同時也可以減少服務器的壓力使用computed緩存數據,…

【圖像算法 - 14】精準識別路面墻體裂縫:基于YOLO12與OpenCV的實例分割智能檢測實戰(附完整代碼)

摘要: 裂縫是結構健康的重要隱患,傳統人工巡檢耗時耗力且易遺漏。本文將帶您利用當前最先進的YOLO12實例分割模型,構建一個高效、準確、更高精度的裂縫檢測系統。我們將從數據準備、模型訓練到結果可視化,手把手實現一個完整的項目…

“讓機器人更智慧 讓具身體更智能”北京世界機器人大會行業洞察

2025年8月8日,世界機器人大會在北京盛大開幕。本屆大會以“讓機器人更智慧 讓具身體更智能”為主題,由中國電子學會、世界機器人合作組織主辦,包括開幕式、閉幕式、論壇等。同期舉辦世界機器人博覽會、世界機器人大賽等活動,打造了…

PHP如何使用JpGraph生成折線圖?

JpGraph是一個功能強大的PHP圖表庫,它通過封裝GD庫函數,為開發者提供了簡單高效的數據可視化解決方案。作為專門用于繪制統計圖的面向對象庫,JpGraph支持創建折線圖、柱狀圖、餅圖等20余種圖表類型,并能自動處理坐標軸、刻度、圖例…

超級云平臺:重構數字生態的“超級連接器“

在數字經濟浪潮席卷全球的今天,企業數字化轉型已從"選擇題"變為"必答題"。然而,傳統云服務模式因技術壁壘高、資源分散、協同效率低等問題,讓許多企業在數字化轉型中陷入"上云易、用云難"的困境。 在此背景下,一種以"全域資源整合+智能…

https如何保證傳遞參數的安全

HTTPS 并非直接“加密參數”,而是通過一整套加密傳輸機制,確保客戶端與服務器之間所有通信內容(包括 URL 參數、表單數據、Cookie 等)在傳輸過程中不被竊聽、篡改或偽造。其核心安全保障來自以下技術實現: 一、核心加密…

OpenHarmony之打造全場景智聯基座的“分布式星鏈 ”WLAN子系統

1. 技術架構概覽 無線局域網(Wireless Local Area Networks,WLAN),是通過無線電、紅外光信號或者其他技術發送和接收數據的局域網,用戶可以通過WLAN實現結點之間無物理連接的網絡通訊。常用于用戶攜帶可移動終端的辦公、公眾環境中。 WLAN組件子系統為用戶提供WLAN基礎功…

JMeter(入門篇)

一.簡介 JMeter 是 Apache 組織使用 Java 開發的一款測試工具。 1、可以用于對服務器、網絡或對象模擬巨大的負載 2、通過創建帶有斷言的腳本來驗證程序是否能返回期望的結果 二.優缺點 優點: 開源、免費 跨平臺 支持多協議 小巧 功能強大 缺點&#xff…

Lecture 12: Concurrency 5

回顧:并行用餐哲學家讀者/作者問題哲學家進餐問題方案三:最大化并行需要一個更復雜的解決方案來實現最大的并行性 解決方案使用:state[N]:每個哲學家的當前狀態(THINKING, HUNGRY, EATING&#…

UniApp 微信小程序之間跳轉指南

概述 在UniApp開發中,經常需要實現從當前小程序跳轉到其他微信小程序的功能。本文檔詳細介紹了如何在UniApp中實現微信小程序之間的跳轉。 核心API uni.navigateToMiniProgram() 這是UniApp提供的用于跳轉到其他微信小程序的核心API。 基本語法 uni.navigateToMiniP…

基于SpringBoot+Vue的養老院管理系統的設計與實現 智能養老系統 養老架構管理 養老小程序

🔥作者:it畢設實戰小研🔥 💖簡介:java、微信小程序、安卓;定制開發,遠程調試 代碼講解,文檔指導,ppt制作💖 精彩專欄推薦訂閱:在下方專欄&#x1…

TRAE調教指南:用6A工作流項目規則+5S敏捷個人規則打造高效AI開發流程

TRAE調教指南:用6A工作流項目規則5S敏捷個人規則打造高效AI開發流程 引言:從"AI瞎寫"到"精準交付"的實戰手冊一、什么是Rules:讓AI"聽話"的底層邏輯1. 告別重復指令疲勞2. 實現"千人千面"的個性化適…