通過 SQL 實現行轉列(列的資料條目、資料分佈是不規則的)
--建立測試表
create table test(report_date date,activity_name varchar2(15),amount number);
insert into test values(to_date('2015-10-01','yyyy-mm-dd'),'活動一',1300);
insert into test values(to_date('2015-10-02','yyyy-mm-dd'),'活動一',500);
insert into test values(to_date('2015-10-02','yyyy-mm-dd'),'活動二',800);
insert into test values(to_date('2015-10-03','yyyy-mm-dd'),'活動一',900);
insert into test values(to_date('2015-10-03','yyyy-mm-dd'),'活動二',1500);
insert into test values(to_date('2015-10-03','yyyy-mm-dd'),'活動三',3500);
commit;
SQL> select * from test;
REPORT_DAT ACTIVITY_NAME AMOUNT
---------- --------------- ----------
2015-10-01 活動一 1300
2015-10-02 活動一 500
2015-10-02 活動二 800
2015-10-03 活動一 900
2015-10-03 活動二 1500
2015-10-03 活動三 3500
已選擇6行。
想要實現的效果是:
---------- --------------- ----------
2015-10-01 活動一 1300
2015-10-02 活動一 500 活動二 800
2015-10-03 活動一 900 活動二 1500 活動三 3500
可以發現,列的資料條目是不規則的
對於這種需求,想要通過SQL實現的話,不能使用 decode 函式(列的條目相同的需求,可以使用 decode 函式來實現)
方法一,在 Oracle 11g,可以使用 LISTAGG 這個分析函式來實現
SELECT report_date,
LISTAGG(activity_name || ', ' || amount || ', ') within GROUP(ORDER BY report_date) info
FROM test
GROUP BY report_date;
REPORT_DAT INFO
---------- ---------------------------------------------
2015-10-01 活動一, 1300,
2015-10-02 活動二, 800, 活動一, 500,
2015-10-03 活動二, 1500, 活動三, 3500, 活動一, 900,
方法二,通過層次函式 CONEECT BY 實現
with tmp as
(select report_date, activity_name || ', ' || amount info, rn
from (select report_date,
activity_name,
ROW_NUMBER() OVER(PARTITION BY report_date ORDER BY activity_name) rn,
amount
from test))
select a.report_date, b.message
from(
select report_date, max(level_no) no
from(
select report_date, LTRIM(SYS_CONNECT_BY_PATH(info, '/ '), '/') message, level level_no
from tmp
connect by prior report_date = report_date and prior rn = rn + 1)
group by report_date) a,(
select report_date, LTRIM(SYS_CONNECT_BY_PATH(info, '/ '), '/') message, level level_no
from tmp
connect by prior report_date = report_date and prior rn = rn - 1) b
where a.report_date = b.report_date and a.no = b.level_no;
方法三,在 Oracle 10g ,使用 WM_CONCAT 函式來實現
SELECT report_date, MAX(info)
from (SELECT report_date,
WM_CONCAT(activity_name || ', ' || amount || ', ') OVER (PARTITION BY report_date ORDER BY report_date) info
FROM test)
GROUP BY report_date;
create table test(report_date date,activity_name varchar2(15),amount number);
insert into test values(to_date('2015-10-01','yyyy-mm-dd'),'活動一',1300);
insert into test values(to_date('2015-10-02','yyyy-mm-dd'),'活動一',500);
insert into test values(to_date('2015-10-02','yyyy-mm-dd'),'活動二',800);
insert into test values(to_date('2015-10-03','yyyy-mm-dd'),'活動一',900);
insert into test values(to_date('2015-10-03','yyyy-mm-dd'),'活動二',1500);
insert into test values(to_date('2015-10-03','yyyy-mm-dd'),'活動三',3500);
commit;
SQL> select * from test;
REPORT_DAT ACTIVITY_NAME AMOUNT
---------- --------------- ----------
2015-10-01 活動一 1300
2015-10-02 活動一 500
2015-10-02 活動二 800
2015-10-03 活動一 900
2015-10-03 活動二 1500
2015-10-03 活動三 3500
已選擇6行。
想要實現的效果是:
---------- --------------- ----------
2015-10-01 活動一 1300
2015-10-02 活動一 500 活動二 800
2015-10-03 活動一 900 活動二 1500 活動三 3500
可以發現,列的資料條目是不規則的
對於這種需求,想要通過SQL實現的話,不能使用 decode 函式(列的條目相同的需求,可以使用 decode 函式來實現)
方法一,在 Oracle 11g,可以使用 LISTAGG 這個分析函式來實現
SELECT report_date,
LISTAGG(activity_name || ', ' || amount || ', ') within GROUP(ORDER BY report_date) info
FROM test
GROUP BY report_date;
REPORT_DAT INFO
---------- ---------------------------------------------
2015-10-01 活動一, 1300,
2015-10-02 活動二, 800, 活動一, 500,
2015-10-03 活動二, 1500, 活動三, 3500, 活動一, 900,
方法二,通過層次函式 CONEECT BY 實現
with tmp as
(select report_date, activity_name || ', ' || amount info, rn
from (select report_date,
activity_name,
ROW_NUMBER() OVER(PARTITION BY report_date ORDER BY activity_name) rn,
amount
from test))
select a.report_date, b.message
from(
select report_date, max(level_no) no
from(
select report_date, LTRIM(SYS_CONNECT_BY_PATH(info, '/ '), '/') message, level level_no
from tmp
connect by prior report_date = report_date and prior rn = rn + 1)
group by report_date) a,(
select report_date, LTRIM(SYS_CONNECT_BY_PATH(info, '/ '), '/') message, level level_no
from tmp
connect by prior report_date = report_date and prior rn = rn - 1) b
where a.report_date = b.report_date and a.no = b.level_no;
方法三,在 Oracle 10g ,使用 WM_CONCAT 函式來實現
SELECT report_date, MAX(info)
from (SELECT report_date,
WM_CONCAT(activity_name || ', ' || amount || ', ') OVER (PARTITION BY report_date ORDER BY report_date) info
FROM test)
GROUP BY report_date;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26506993/viewspace-1869259/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- sql實現行轉列SQL
- 資料結構--單連結串列(通過陣列實現)資料結構陣列
- 利用Jackson的JsonFilter來實現動態過濾資料列(資料列權JSONFilter
- 資料結構之陣列和矩陣--矩陣&不規則二維陣列資料結構陣列矩陣
- Excel實現動態行轉列(資料透視表)Excel
- 通過佇列實現棧OR通過棧實現佇列佇列
- 通過命令列連線oracle資料庫/進入sql plus命令列Oracle資料庫SQL
- 千萬條資料,Stack Overflow 是如何實現快速分頁的?
- 通過Vue的過濾器實現資料的資料脫敏Vue過濾器
- python實現列1的資料補充到列2Python
- EMQ X 與 HStreamDB 整合實踐:通過規則引擎實現資料儲存MQ
- 資料庫SQL開發命名規則 (轉)資料庫SQL
- MySQL列轉行巧錄資料MySql
- /*列轉行查詢表資料*/
- SQL Server資料庫基礎之行資料轉換為列資料SQLServer資料庫
- 【原創】通過資料字典操作刪除表的列
- 【SQL】實現每隔一分鐘插入一條資料SQL
- 資料結構-棧(通過陣列和單向連結串列實現)資料結構陣列
- SQL 行轉列,列轉行SQL
- char(16)列的資料轉換
- 通過cmd命令列連線mysql資料庫命令列MySql資料庫
- sql的行轉列(PIVOT)與列轉行(UNPIVOT)SQL
- 大資料謝列3:Hdfs的HA實現大資料
- 用XML/XSLT將行資料轉換為列資料 (轉)XML
- 通過 ProxySQL 在 TiDB 上實現 SQL 的規則化路由SQLTiDB路由
- C# 一維陣列如何快速實現陣列元素的資料型別的轉換?C#陣列資料型別
- 使用Oracle 11g函式Pivot實現資料聚合行轉列Oracle函式
- 詳細分析棧和佇列的資料結構的實現過程(Java 實現)佇列資料結構Java
- xml資料轉陣列XML陣列
- js實現資料結構--陣列JS資料結構陣列
- js實現資料結構--佇列JS資料結構佇列
- 資料結構實驗 多維陣列的實現資料結構陣列
- 【資料結構】佇列(順序佇列、鏈佇列)的JAVA程式碼實現資料結構佇列Java
- 資料庫知識點(2)——行轉列資料庫
- java 資料結構 之 佇列的實現 (二)Java資料結構佇列
- Excel 如何批次將矩陣(多行多列)資料轉為單行或單列資料Excel矩陣
- Oracle行轉列、列轉行的Sql語句總結OracleSQL
- sql 多組條資料取最新的一條資料SQL