Select

SQL 中的自定義 CSV“報告”

  • May 17, 2017

我有兩個從 ERP(發票)中提取的 SQL 數據表,第一個包含發票的“head”(invoice_number、date、customer,…),第二個表包含所有發票的“行”(good_description,qty , 價錢, …)

簡化:

 T1.ID  |  T1.COL_A | T1.COL_B           T2.T1_ID |  T2.COL_A | T2.COL_B
 -----------------------------           ------------------------------- 
  1     |    AAA    |    BBB                 1    |    eee    |    fff
  2     |    CCC    |    DDD                 1    |    ggg    |    hhh
                                             2    |    iii    |    jjj   
                                             2    |    kkk    |    lll

如果我SELECT按欄位連接兩個表,ID它將給出:

          T1.COL_A  |  T1.COL_B  |  T2.COL_A | T2.COL_B
         ---------------------------------------------- 
  1          AAA    |    BBB     |    eee    |    fff
  1          AAA    |    BBB     |    ggg    |    hhh
  2          CCC    |    DDD     |    iii    |    jjj   
  2          CCC    |    DDD     |    kkk    |    lll

好的很簡單。

問題是我需要一種特定的格式來將數據導入另一個 ERP,一種像這樣製作的 CSV 格式:

   ROW_TIPE    ;  T1.COL_A  ;  T1.COL_B  ;  T2.COL_A ; T2.COL_B
---------------------------------------------------------------- 
 INVOICE_HEAD  ;     AAA    ;    BBB     ;           ; 
 INVOICE_ROW   ;            ;            ;    eee    ;    fff
 INVOICE_ROW   ;            ;            ;    ggg    ;    hhh
 INVOICE_HEAD  ;     CCC    ;    DDD     ;           ;          
 INVOICE_ROW   ;            ;            ;    iii    ;    jjj  
 INVOICE_ROW   ;            ;            ;    kkk    ;    lll

因此,這些行被“分組”並且不重複,並且在第一列插入了要由 ERP 處理的行類型,以導入數據(如果是INVOICE_HEADINVOICE_ROW

在 SQL 中實現此結果的最佳方法是什麼?

數據來自 Pervasive Btrieve。我設法從兩個 CSV 文件(每個表一個)中提取發票數據。然後我導入了一個 SQLite 來進行所需的操作,以獲得可以在新的 ERP 軟體中導入的格式。

我可以建議使用視圖嗎?考慮下表(和測試數據):

-- T1
create table ihead (
 id number primary key
, col_a varchar2(32)
, col_b varchar2(32)
);

-- T2
create table irow (
 headid number references ihead(id)
, col1 varchar2(32)
, col2 varchar2(32)
, irowid number primary key
);

在第二個表(您稱為 T2)中,應該以某種方式對行進行編號,否則將很難將發票詳細資訊按正確的順序排列 - 正如@Bill 所暗示的那樣。

-- test data
begin
 insert into ihead values (1, 'AAA', 'BBB');
 insert into ihead values (2, 'CCC', 'DDD');
 insert into irow values (1, 'eee', 'fff', 1);
 insert into irow values (1, 'ggg', 'hhh', 2);
 insert into irow values (2, 'iii', 'jjj', 3);
 insert into irow values (2, 'kkk', 'lll', 4);  
end;

我會先創建一個連接,並將其儲存為視圖,如下所示:

-- join, similar to the first select you have written

create or replace view alldetails
as
select
 H.id, H.col_a, H.col_b, R.col1, R.col2, R.irowid
from 
 ihead H join irow R on id = headid;

檢查輸出:

select * from alldetails;
-- output
ID COL_A  COL_B  COL1  COL2  IROWID
1  AAA    BBB    eee   fff   1
1  AAA    BBB    ggg   hhh   2
2  CCC    DDD    iii   jjj   3
2  CCC    DDD    kkk   lll   4

第二種視圖:獲取所有INVOICE_HEADS(第一次選擇),然後INVOICE_ROWS(第二次選擇)

create or replace view idetails (c1, c2, c3, c4, irow)
as
select 'INVOICE_HEAD', col_a, col_b, col1, col2 from alldetails
where irowid in (
 select min(irowid) from iheader group by id
)
union
select 'INVOICE_ROW', null, null, col1, col2 from alldetails
where irowid not in (
 select min(irowid) from iheader group by id
)

現在我們可以:

select * from idetails order by irow
-- output
C1              C2      C3      C4      IROW
INVOICE_HEAD    AAA     BBB     eee     fff
INVOICE_ROW     -       -       ggg     hhh
INVOICE_HEAD    CCC     DDD     iii     jjj
INVOICE_ROW     -       -       kkk     lll

通過執行以下命令獲得最終輸出:

select 
 c1 ||';'|| c2 ||';'|| c3 ||';'|| c4 ||';'|| irow
from idetails
order by irow


-- final output (some padding added manually,
-- but can be done with RPAD or LPAD)

INVOICE_HEAD ; AAA ; BBB ; eee ; fff
INVOICE_ROW  ;     ;     ; ggg ; hhh
INVOICE_HEAD ; CCC ; DDD ; iii ; jjj
INVOICE_ROW  ;     ;     ; kkk ; lll

更新 2017-05-17(要求已更改)

-- leave the first view as it is,
-- change the second view to be:
create or replace view idetails (
 c1, c2, c3, id, c4, c5, irowid )
as
select distinct 
 'INVOICE_HEAD', col_a, col_b, headid, null, null, 0 
from alldetails
union
select 
 'INVOICE_ROW', null, null, headid, col1, col2, irowid 
from alldetails;

然後,選擇您需要的所有列(注意:ORDER BY 子句中有 2 列):

select 
 c1 ||';'|| c2 ||';'|| c3 ||';'|| c4 ||';'|| c5
from idetails
order by id, irowid;

輸出(為清楚起見,手動添加填充):

INVOICE_HEAD;AAA;BBB;   ;
INVOICE_ROW ;   ;   ;eee;fff
INVOICE_ROW ;   ;   ;ggg;hhh
INVOICE_HEAD;CCC;DDD;   ;
INVOICE_ROW ;   ;   ;iii;jjj
INVOICE_ROW ;   ;   ;kkk;lll

引用自:https://dba.stackexchange.com/questions/173651