2017-06-02 149 views
0

我有一個表 -如何運行Teradata遞歸查詢來查找表中的層次結構?

ID  Name 
A  Steve 
AA  Carla 
AAA  Anthony 
AAAA  Martin 
AAB  Casey 
AABA  Mark 

在輸入數據上述

•員工「史蒂夫」具有ID「A」。像這樣的單個字符表示客戶沒有任何推薦就購買了該產品。

•從Steve的推薦中,Carla購買了另一種產品並獲得了「AA」的ID。在這裏,卡拉的客戶代碼「AA」表示他被某個客戶使用ID「A」引用。

•從Carla的推薦中,Anthony和Casey分別購買了產品並分別獲得了「AAA」和「AAB」的ID,表示它們由Carla以ID「AA」引用。

•每個推介的ID都有一個模式,可以在鏈中一直翻譯爲ID。

我需要這個錶轉換爲以下使用Teradata的SQL遞歸查詢ONLY

DATA LINEAGE 
1>Steve 
1.1>>Carla 
1.1.1>>>Anthony 
1.1.1.1>>>>Martin 
1.1.2>>>Casey 
1.1.2.1>>>>Marc 

以下幾點是值得一提的關於此輸出表:

•多個引用一個特定的人都在字母順序。例如,安東尼&凱西以字母升序顯示,安東尼獲得1.1.1的前綴,而凱西獲得1.1.2。

•可能有多個客戶開始連鎖店,即沒有任何推介的直接客戶。

•所有直接客戶在其輸出開始時應該有整數(沒有點和單箭頭)。

•開始供應鏈的客戶,即直接客戶也應該按字母順序排列。

•前綴符號「>」的數量對應於層次的深度。

+0

這看起來像一個遞歸語句的輸出。這不是一個很好的輸入,因爲父/子關係是基於單個字段中字符的位置。此外,基於多次推薦的增量需求表明需要一個DENSE_RANK()窗口函數,這在遞歸CTE內是不可能的。爲什麼迫使一個遞歸的CTE來處理這個問題,而不是像'REG_SPLIT_TO_TABLE'那樣用'XML_AGG()','SUBSTRING()'和'LENGTH()'來再次推回事物呢? – JNevill

+0

**(1)**解釋與實際數據不符(Mary,Jonathan&Koen?Mike?)**(2)**正在使用什麼字符構造實際數據中的「ID」值一個-...) ? **(3)** ** _「僅限」_ **?而不是? –

回答

1

這不是遞歸的,但我不認爲它需要。

CREATE MULTISET VOLATILE TABLE voltest 
(
    id VARCHAR(50), 
    nm VARCHAR(50) 
) PRIMARY INDEX (id) ON COMMIT PREServe ROWS; 
INSERT INTO voltest(id,nm) VALUES ('A','Steve'); 
INSERT INTO voltest(id,nm) VALUES ('AA','Carla'); 
INSERT INTO voltest(id,nm) VALUES ('AAA','Anthony'); 
INSERT INTO voltest(id,nm) VALUES ('AAAA','Martin'); 
INSERT INTO voltest(id,nm) VALUES ('AAB','Casey'); 
INSERT INTO voltest(id,nm) VALUES ('AABA','Mark'); 

SELECT 
    path || bumpers || nm as "DATA LINEAGE" 
FROM 
(
    SELECT 
     oreplace(TRIM(TRAILING '.' FROM (XMLAGG(trim(id_number) || '.' ORDER BY token_index) (VARCHAR(50)))), ' ', '') as path, 
     bumpers, 
     nm 
    FROM 
     (
      SELECT to_number(token, 'xxxxx')-9 as id_number, nm, token, token_index, SUBSTRING('>>>>>>>>>>>>>>' FROM 1 FOR max(token_index) OVER (PARTITION BY nm)) as bumpers 
      FROM TABLE (
       REGEXP_SPLIT_TO_TABLE(voltest.nm, volTest.id, '', 'i') 
        RETURNS (nm VARCHAR(50) character set unicode, token_index integer, token varchar(50) CHARACTER SET UNICODE) 
       ) AS dt 
     ) sub 
    GROUP BY nm, bumpers 
) sub2 

regexp_split_to_table將在id列的每一個字符分割成它自己的一行處爲重點。我們還捕獲了token_index中的位置。拆分出的字符在token中被捕獲。

我們使用to_number吐出你token的十六進制表示的整數值,並減去9於是A = 1,B = 2,依此類推。

我們對token_index使用窗口函數MAX()爲每個名稱確定要爲該名稱拉動多少個箭頭>

然後我們用XMLAGG連同一個句點分隔符(修剪掉最後一個)來彙總標記字符串。

這會吐出如下:

+-------------------+ 
| DATA LINEAGE | 
+-------------------+ 
| 1.1.1.1>>>>Martin | 
| 1.1.1>>>Anthony | 
| 1.1.2.1>>>>Mark | 
| 1.1>>Carla  | 
| 1>Steve   | 
| 1.1.2>>>Casey  | 
+-------------------+ 
+0

謝謝JNevill。我會嘗試這個解決方案。雖然遞歸不是必需的,但我正在學習SQL遞歸查詢,這是給我的一個難題,因此要求遞歸SQL。 :) –

+0

你可以通過使用'substring()'並通過迭代跟蹤遞歸深度來實現遞歸。但它會變得非常難看。通常,遞歸查詢對結構化爲'child |的數據最有效父母|屬性...'來產生像'node |這樣的數據路徑>到>節點|深度|屬性...'但是在你的情況下你的數據路徑>到>節點|屬性「,所以它更像是最終的結果。 – JNevill