Oracle 分組彙總統計函式的使用
問題描述
具有原始資料資訊如下:
想得到如下彙總資訊(統計每個產品所有資料日期 TRANS_DATE
、所有客戶來源 CUSTOMER_SOURCE
下的金額 AMT
、份額 SHARES
總值):
問題解決
grouping(columnA)函式的意思:當前行如果是由rollup彙總產生的,那麼columnA這個欄位值為1否則為0
SELECT
t.PRD_CODE,
t.TRANS_DATE,
-- 如果當前行是由 TRANS_DATE 和 CUSTOMER_SOURCE 彙總產生的,則將CUSTOMER_SOURCE列的值設定為"單產品彙總"
decode(grouping(t.TRANS_DATE)+grouping(t.CUSTOMER_SOURCE),2, '單產品彙總',t.CUSTOMER_SOURCE) CUSTOMER_SOURCE,
SUM(AMT),
SUM(SHARES)
FROM
T_PRODUCT t
-- 統計每個產品的所有TRANS_DATE、CUSTOMER_SOURCE 進行彙總
GROUP BY rollup(t.TRANS_DATE, t.CUSTOMER_SOURCE),
-- 按PRD_CODE分組,每個產品出一條彙總資訊
t.PRD_CODE
-- 去除 CUSTOMER_SOURCE 中的 null 值
having
-- 保留原始資料
t.CUSTOMER_SOURCE is not null
-- 保留 "單產品彙總" 彙總記錄
or (t.trans_date is null and t.CUSTOMER_SOURCE is null)
ORDER BY
PRD_CODE
執行效果如下:
可能有人對上述 SQL 還不完全理解,那我們再來具體分析一下:
decode
decode(條件,值1,返回值1,值2,返回值2,…值n,返回值n,預設值)
該函式的含義如下:
IF 條件=值1 THEN
RETURN(翻譯值1)
ELSIF 條件=值2 THEN
RETURN(翻譯值2)
......
ELSIF 條件=值n THEN
RETURN(翻譯值n)
ELSE
RETURN(預設值)
END IF
decode(grouping(t.TRANS_DATE)+grouping(t.CUSTOMER_SOURCE),2, '單產品彙總',t.CUSTOMER_SOURCE) CUSTOMER_SOURCE,
的含義:
如果grouping(t.TRANS_DATE)+grouping(t.CUSTOMER_SOURCE) = 2
,使用 ‘單產品彙總’ 文字填充 CUSTOMER_SOURCE 欄位值。
grouping
grouping(t.TRANS_DATE)
的意思:當前行如果是由TRANS_DATE彙總產生的,那麼grouping(t.TRANS_DATE)為1,否則為0
having 條件
首先看一下不新增 having 條件的 SQL:
SELECT
t.PRD_CODE,
t.TRANS_DATE,
decode(grouping(t.TRANS_DATE)+grouping(t.CUSTOMER_SOURCE),2, '單產品彙總',t.CUSTOMER_SOURCE) CUSTOMER_SOURCE,
SUM(AMT),
SUM(SHARES)
FROM
T_PRODUCT t
GROUP BY rollup(t.TRANS_DATE, t.CUSTOMER_SOURCE),
t.PRD_CODE
-- having 1=2
-- or (t.trans_date is null and t.CUSTOMER_SOURCE is null)
-- or (t.trans_date is not null and t.CUSTOMER_SOURCE is not null)
ORDER BY
PRD_CODE
結果集如下:
我們發現其中有一些 CUSTOMER_SOURCE 為 null 的記錄(統計每個產品PRD_CODE
每個資料日期TRANS_DATE
的金額、餘額合計),但我們並不想要這些記錄,我只想要統計每個產品PRD_CODE
所有資料日期TRANS_DATE
、所有客戶來源CUSTOMER_SOURCE
的合計,所以需要過濾掉 CUSTOMER_SOURCE 為 null 的記錄,保留
CUSTOMER_SOURCE 不為 null 的資料。即在 group by 後面新增 having t.CUSTOMER_SOURCE is not null
SELECT
t.PRD_CODE,
t.TRANS_DATE,
decode(grouping(t.TRANS_DATE)+grouping(t.CUSTOMER_SOURCE),2, '單產品彙總',t.CUSTOMER_SOURCE) CUSTOMER_SOURCE,
SUM(AMT),
SUM(SHARES)
FROM
T_PRODUCT t
GROUP BY rollup(t.TRANS_DATE, t.CUSTOMER_SOURCE),
t.PRD_CODE
having
t.CUSTOMER_SOURCE is not null
ORDER BY
PRD_CODE
這時又發現沒有了合計資料了,因為合計資料的 CUSTOMER_SOURCE 原本也為 null(雖然後來用了"單產品彙總",填充,但查出來的原始 CUSTOMER_SOURCE 為 null),所以被過濾掉了。
於是這時就要修改過濾條件,在 hving 後面新增 or (t.trans_date is null and t.CUSTOMER_SOURCE is null)
SELECT
t.PRD_CODE,
t.TRANS_DATE,
decode(grouping(t.TRANS_DATE)+grouping(t.CUSTOMER_SOURCE),2, '單產品彙總',t.CUSTOMER_SOURCE) CUSTOMER_SOURCE,
SUM(AMT),
SUM(SHARES)
FROM
T_PRODUCT t
GROUP BY rollup(t.TRANS_DATE, t.CUSTOMER_SOURCE),
t.PRD_CODE
having
t.CUSTOMER_SOURCE is not null
or (t.trans_date is null and t.CUSTOMER_SOURCE is null)
ORDER BY
PRD_CODE
此時終於得到我們想要的資料了:每個產品出一條合計記錄(統計所有資料日期、客戶來源的金額、份額合計)
SQL 建表及插入資料語句
CREATE TABLE "test"."T_PRODUCT" (
"TRANS_DATE" NUMBER(8) VISIBLE ,
"PRD_CODE" VARCHAR2(255 BYTE) VISIBLE ,
"CUSTOMER_SOURCE" VARCHAR2(255 BYTE) VISIBLE ,
"AMT" NUMBER(18,2) VISIBLE ,
"SHARES" NUMBER(18,2) VISIBLE
)
TABLESPACE "test"
LOGGING
NOCOMPRESS
PCTFREE 10
INITRANS 1
STORAGE (
INITIAL 65536
NEXT 1048576
MINEXTENTS 1
MAXEXTENTS 2147483645
BUFFER_POOL DEFAULT
)
PARALLEL 1
NOCACHE
DISABLE ROW MOVEMENT
;
COMMENT ON COLUMN "test"."T_PRODUCT"."TRANS_DATE" IS '資料日期';
COMMENT ON COLUMN "test"."T_PRODUCT"."PRD_CODE" IS '產品程式碼';
COMMENT ON COLUMN "test"."T_PRODUCT"."CUSTOMER_SOURCE" IS '客戶來源';
COMMENT ON COLUMN "test"."T_PRODUCT"."AMT" IS '金額';
COMMENT ON COLUMN "test"."T_PRODUCT"."SHARES" IS '份額';
-- ----------------------------
-- Records of "T_PRODUCT"
-- ----------------------------
INSERT INTO "test"."T_PRODUCT" VALUES ('20200101', 'P1_10001', '北京市', '20.22', '22.54');
INSERT INTO "test"."T_PRODUCT" VALUES ('20200202', 'P2_10001', '上海市', '33.33', '34.67');
INSERT INTO "test"."T_PRODUCT" VALUES ('20200202', 'P3_10001', '雲南市', '109.23', '78.35');
INSERT INTO "test"."T_PRODUCT" VALUES ('20200303', 'P1_10001', '濟南市', '44.89', '66.61');
INSERT INTO "test"."T_PRODUCT" VALUES ('20200505', 'P3_10001', '青島市', '50.43', '44.36');
INSERT INTO "test"."T_PRODUCT" VALUES ('20200505', 'P2_10001', '北京市', '62.98', '50.43');
INSERT INTO "test"."T_PRODUCT" VALUES ('20201010', 'P1_10001', '濟南市', '38.07', '39.02');
INSERT INTO "test"."T_PRODUCT" VALUES ('20201010', 'P3_10001', '上海市', '40.32', '48.65');
INSERT INTO "test"."T_PRODUCT" VALUES ('20201010', 'P1_10001', '北京市', '98.23', '55.71');
相關文章
- Oracle函式彙總Oracle函式
- 6、Oracle中的分組函式Oracle函式
- 【彙總】scapy 函式函式
- string 函式彙總函式
- 常用函式彙總函式
- ORACLE中日期和時間函式彙總(轉載)Oracle函式
- 開窗函式彙總函式
- AA常用函式彙總函式
- PHP 常用函式彙總PHP函式
- PHP字串函式彙總PHP字串函式
- MySQL常用函式彙總MySql函式
- Mysql 常用函式(1)- 常用函式彙總MySql函式
- Oracle 統計資訊相關命令彙總Oracle
- python 系統函式呼叫sed分組Python函式
- Excel 特殊分組彙總示例Excel
- MySQL視窗函式彙總MySql函式
- 陣列常用函式彙總陣列函式
- PHP陣列函式彙總PHP陣列函式
- 【彙總】EMQX 函式API、安裝與使用說明MQ函式API
- Openmp Runtime 庫函式彙總(上)函式
- 輸出輸入函式彙總函式
- 分析函式系列之sum(col1) over(partition by col2 order by col3):實現分組彙總或遞增彙總函式
- phpRedis函式使用總結【分類詳細】PHPRedis函式
- Oracle中Decode()函式的使用Oracle函式
- php常用函式彙總.以備查.PHP函式
- MySQL日期和時間函式彙總MySql函式
- excel最常用的八個函式彙總 excel中各函式的用途功能Excel函式
- 區間統計 聚合函式組合器函式
- MySQL - 分組連線欄位函式GROUP_CONCAT的使用MySql函式
- hive常用的一些高階函式彙總Hive函式
- Oracle分組查詢中包含子查詢列,發生ORA-00937:不是單分組函式的錯誤Oracle函式
- Oracle 常用方法彙總Oracle
- Oracle 架構彙總Oracle架構
- PostgreSQL訪問許可權查詢函式彙總和使用舉例SQL訪問許可權函式
- MySQL資料庫中的分組函式ROLLUPMySql資料庫函式
- 如何使用async和await這對組合設計統一的取Access Token的函式AI函式
- 【函式】Oracle12c 列轉行函式使用listagg函式Oracle
- oracle 函式Oracle函式