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函式
- 報告彙總資料使用組函式函式
- oracle常用函式彙總Oracle函式
- Oracle 10gR2分析函式彙總Oracle 10g函式
- mysql與oracle的分組函式MySqlOracle函式
- 6、Oracle中的分組函式Oracle函式
- 常用函式彙總函式
- 【彙總】scapy 函式函式
- 【ROLLUP】Oracle分組函式之ROLLUP魅力Oracle函式
- 【CUBE】Oracle分組函式之CUBE魅力Oracle函式
- 關於Oracle自定義分組函式Oracle函式
- Excel 特殊分組彙總示例Excel
- MySQL常用函式彙總MySql函式
- PHP字串函式彙總PHP字串函式
- string 函式彙總函式
- PHP 常用函式彙總PHP函式
- AA常用函式彙總函式
- 開窗函式彙總函式
- Oracle 最常用功能函式經典彙總Oracle函式
- Oracle - 分組連線欄位函式WMSYS.WM_CONCAT的使用Oracle函式
- Mysql 常用函式(1)- 常用函式彙總MySql函式
- SAP 的CALL FUNCTION 函式彙總Function函式
- Oracle分析函式使用總結Oracle函式
- python 系統函式呼叫sed分組Python函式
- oracle 統計分析函式Oracle函式
- ORACLE中日期和時間函式彙總(轉載)Oracle函式
- PHP陣列函式彙總PHP陣列函式
- 陣列常用函式彙總陣列函式
- PHP字串函式大彙總PHP字串函式
- PHP部分字串函式彙總PHP字串函式
- WordPress模板常用函式彙總函式
- mysql常用函式彙總(分享)MySql函式
- ORA-600 函式彙總函式
- MySQL視窗函式彙總MySql函式
- 常用的PB時間函式彙總函式
- Oracle 統計資訊相關命令彙總Oracle
- 函式及分組統計和資料庫備份,恢復函式資料庫
- Oracle按時間分組統計的sqlOracleSQL