iT邦幫忙

1

請教 SQL

  • 分享至 

  • xImage

Output:
https://ithelp.ithome.com.tw/upload/images/20231219/20001787nhOfRCRd6w.png

Input:
DB fiddle

請教 SQL statement
/images/emoticon/emoticon41.gif

補充兩點:
1.P1 資料只是為建立資料時有得對照,不代表是全部的項目
2.P1,P2,P3,P4...有可能到 Pn

查了一下適用Oracle的T-SQL,叫做PL/SQL
https://www.oracle.com/tw/database/technologies/appdev/plsql.html

可惜電腦沒裝Oracle,不然把T-SQL改寫成PL/SQL應該沒問題的😅😅😅
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
3
一級屠豬士
iT邦大師 1 級 ‧ 2023-12-20 09:21:07
最佳解答

https://ithelp.ithome.com.tw/articles/10340771
https://hackmd.io/@pgsql-tw/B13CK7oVp
https://ithelp.ithome.com.tw/articles/10340780

Oracle 有 Json_Table 這個超強函數.

也可以用PostgreSQL 的 Oracle_FDW 連到Oracle, 用PG產生報表.
做了一點測試:
https://dbfiddle.uk/Yxn-JyU2

CREATE TABLE main
(
  morderno varchar(2),
  mgroup varchar(2),
  mseq numeric(1),
  mitem varchar(3),
  mamt numeric(2),
  munitprice numeric(5)
);

insert into main values
 ('P1','GA',1,'A01',11,111)
,('P1','GA',2,'A02',12,112)
,('P1','GB',1,'B01',13,113)
,('P1','GB',2,'B02',14,114)
,('P1','GC',1,'C01',15,115)
,('P1','GC',2,'C02',16,116)
;

insert into main values 
 ('P2','GA',1,'A01',21,221)
,('P2','GB',1,'B01',22,222)
,('P2','GC',1,'C01',23,223)
;

insert into main values 
 ('P3','GB',2,'B02',31,331)
,('P3','GC',2,'C02',32,332)
;

SELECT * FROM MAIN;

DO LANGUAGE plpgsql $$
DECLARE v_sqlstring VARCHAR  = '';
BEGIN
v_sqlstring := concat('create temp table tmpxt231220e as select null::text as mgroup, ',
                 (select string_agg(concat('NULL::text AS ', 'p', n::text, '_', ch), ' ,'
                        order by n)
                  from (values ('mitem'),('mamt'),('munitprice')) as a(ch)
                     , generate_series(1,5) as n)::text);

EXECUTE(v_sqlstring);
END $$;


with t1(js1) as (
select jsonb_build_object('mgroup', mgroup)
    || jsonb_object_agg(lower(morderno) || '_mitem', mitem)
    || jsonb_object_agg(lower(morderno) || '_mamt', mamt)
    ||jsonb_object_agg(lower(morderno) || '_munitprice', munitprice)
  from main
 group by mgroup, mitem
)
select (jsonb_populate_recordset(null::tmpxt231220e, jsonb_build_array(js1))).*
  from t1
 order by mgroup;

https://ithelp.ithome.com.tw/upload/images/20231220/20050647wTqiPge8GX.png

/images/emoticon/emoticon41.gif

就差一點點了「全部是NULL」

create global temporary table tmpxt231220e as select 'null' as mgroup, 'null' AS p1_mitem ,'null' AS p1_mamt ,'null' AS p1_munitprice ,'null' AS p2_mitem ,'null' AS p2_mamt ,'null' AS p2_munitprice ,'null' AS p3_mitem ,'null' AS p3_mamt ,'null' AS p3_munitprice ,'null' AS p4_mitem ,'null' AS p4_mamt ,'null' AS p4_munitprice ,'null' AS p5_mitem ,'null' AS p5_mamt ,'null' AS p5_munitprice
WITH t1 AS (
    SELECT JSON_OBJECT(
               'mgroup' VALUE mgroup,
               lower(morderno) || '_mitem' VALUE JSON_ARRAYAGG(mitem),
               lower(morderno) || '_mamt' VALUE JSON_ARRAYAGG(mamt),
               lower(morderno) || '_munitprice' VALUE JSON_ARRAYAGG(munitprice)
           ) AS js1,
           mgroup  -- Add mgroup to the group by
    FROM main
    GROUP BY mgroup, lower(morderno)  -- Include lower(morderno) in the group by
)
SELECT *
FROM JSON_TABLE(
         (SELECT JSON_ARRAYAGG(js1) AS json_array FROM t1),
         '$[*]'
         COLUMNS (
             mgroup VARCHAR2(100) PATH '$.mgroup',
             mitem VARCHAR2(100) FORMAT JSON PATH '$.*."_mitem"',
             mamt VARCHAR2(100) FORMAT JSON PATH '$.*."_mamt"',
             munitprice VARCHAR2(100) FORMAT JSON PATH '$.*."_munitprice"'
         )
     ) AS tmpxt231220e
ORDER BY mgroup;
0
純真的人
iT邦大師 1 級 ‧ 2023-12-19 22:18:04

幫海棉大大圖解XD...

https://ithelp.ithome.com.tw/upload/images/20231219/20061369Ickc77fJMb.png

看樣子~閒閒寫T-SQL來解決@@...雖然不是oracle
/images/emoticon/emoticon01.gif

CREATE TABLE main(
  morderno varchar(2),
  mgroup varchar(2),
  mseq int,
  mitem varchar(3),
  mamt int,
  munitprice int
)

insert into main values
 ('P1','GA',1,'A01',11,111)
,('P1','GA',2,'A02',12,112)
,('P1','GB',1,'B01',13,113)
,('P1','GB',2,'B02',14,114)
,('P1','GC',1,'C01',15,115)
,('P1','GC',2,'C02',16,116)

insert into main values 
 ('P2','GA',1,'A01',21,221)
,('P2','GB',1,'B01',22,222)
,('P2','GC',1,'C01',23,223)

insert into main values 
 ('P3','GB',2,'B02',31,331)
,('P3','GC',2,'C02',32,332)

Declare @StrTital1 NVARCHAR(Max) =''
Declare @StrTital2 NVARCHAR(Max) =''
Declare @StrTital3 NVARCHAR(Max) =''
Declare @StrTital4 NVARCHAR(Max) =''
Declare @StrTital5 NVARCHAR(Max) =''
Declare @StrTital6 NVARCHAR(Max) =''
Declare @StrTital7 NVARCHAR(Max) =''
Declare @StrSQL NVARCHAR(Max) =''


Select @StrTital1= @StrTital1+QUOTENAME(morderno+' item')+N',' From main Group By morderno
Select @StrTital2= @StrTital2+QUOTENAME(morderno+' amt')+N',' From main Group By morderno
Select @StrTital3= @StrTital3+QUOTENAME(morderno+' unitprice')+N',' From main Group By morderno
Select @StrTital4= @StrTital4+('max(['+morderno+' item]) ['+morderno+' item]')+','+('max(['+morderno+' amt]) ['+morderno+' amt]')+','+('max(['+morderno+' unitprice]) ['+morderno+' unitprice]')+',' From main Group By morderno
Select @StrTital5= @StrTital5+('['+morderno+' item]')+','+(''''' ['+morderno+' amt]')+','+(''''' ['+morderno+' unitprice]')+',' From main Group By morderno
Select @StrTital6= @StrTital6+(''''' ['+morderno+' item]')+','+('['+morderno+' amt]')+','+(''''' ['+morderno+' unitprice]')+',' From main Group By morderno
Select @StrTital7= @StrTital7+(''''' ['+morderno+' item]')+','+(''''' ['+morderno+' amt]')+','+('['+morderno+' unitprice]')+',' From main Group By morderno
Set @StrTital1=  Left(@StrTital1, Len(@StrTital1)-1) 
Set @StrTital2=  Left(@StrTital2, Len(@StrTital2)-1) 
Set @StrTital3=  Left(@StrTital3, Len(@StrTital3)-1) 
Set @StrTital4=  Left(@StrTital4, Len(@StrTital4)-1) 
Set @StrTital5=  Left(@StrTital5, Len(@StrTital5)-1) 
Set @StrTital6=  Left(@StrTital6, Len(@StrTital6)-1) 
Set @StrTital7=  Left(@StrTital7, Len(@StrTital7)-1) 

Set @StrSQL= N'
	select mgroup
	,'+@StrTital4+'
	from ((
		Select mgroup
		,mgroupnum
		,'+@StrTital5+'
		From
		(
			Select mgroup
			,morderno + '' item'' morderno
			,mgroup+Convert(varchar,mseq) mgroupnum
			,mitem 
			From main
		) As a1
		pivot
		(
			max(mitem) 
			For morderno IN ('+@StrTital1+N')
		) As a2
	)union all(
		Select mgroup
		,mgroupnum
		,'+@StrTital6+'
		From
		(
			Select mgroup
			,morderno + '' amt'' morderno
			,mgroup+Convert(varchar,mseq) mgroupnum
			,mamt 
			From main
		) As a1
		pivot
		(
			max(mamt) 
			For morderno IN ('+@StrTital2+N')
		) As a2
	)union all(
		Select mgroup
		,mgroupnum
		,'+@StrTital7+'
		From
		(
			Select mgroup
			,morderno + '' unitprice'' morderno
			,mgroup+Convert(varchar,mseq) mgroupnum
			,munitprice 
			From main
		) As a1
		pivot
		(
			max(munitprice) 
			For morderno IN ('+@StrTital3+N')
		) As a2
	)) k
	group by mgroup
	,mgroupnum
'
--print @StrSQL

EXEC sp_executesql @StrSQL 

go

Drop Table main

https://ithelp.ithome.com.tw/upload/images/20231220/2006136967RhJgs7RP.png


查了一下適用Oracle的T-SQL,叫做PL/SQL
https://www.oracle.com/tw/database/technologies/appdev/plsql.html

可惜電腦沒裝Oracle,不然把T-SQL改寫成PL/SQL應該沒問題的^_^

rogeryao iT邦超人 8 級 ‧ 2023-12-20 08:49:44 檢舉

好像...珍瓏棋局...

我看到的是...不用直轉橫...
迴圈內用 MGROUP Left join N 次
最後在想辦法去改欄位名稱

不然會 union all 不完

沒有union all不完呀@@..
我只有針對 item amt unitprice
這三個固定名稱才union all
他的欄位變數是 morderno ,這個才會導致欄位無限多~

/images/emoticon/emoticon41.gif

1
尼克
iT邦大師 1 級 ‧ 2023-12-19 22:49:02

/images/emoticon/emoticon41.gif

由於欄的部份無法先預知
似乎無法使用 case solution...

0
fuzzylee1688
iT邦研究生 3 級 ‧ 2023-12-20 14:41:48

我都是用tableau直接拉表的.

/images/emoticon/emoticon41.gif

我要發表回答

立即登入回答