2016-08-23 52 views

回答

0

使用Scalar JS UDF標準SQL)< - 將是我的選擇

CREATE TEMPORARY FUNCTION collapse_repeated(pathway STRING) 
RETURNS STRING LANGUAGE js AS """ 
    var items = pathway.split('->'); 
    short = ''; elem = items[0]; count = 0; 
    for (var i = 0; i < items.length; i++) { 
    if (items[i] !== elem) { 
     if (short.length > 0) {short += '->'} 
     short += elem; if (count > 1) {short += '(x' + count.toString() + ')';} 
     elem = items[i]; count = 1; 
    } else { 
     count++; 
    } 
    } 
    if (short.length > 0) {short += '->'} 
    short += elem; if (count > 1) {short += '(x' + count.toString() + ')';} 
return short; 
"""; 

WITH YourTable AS (
    SELECT "Item1->Item2->Item2->Item2->Item3->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item2->Item3->Item3->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item4" AS pathway 
    UNION ALL SELECT "Item1->Item2->Item2->Item3->Item1->Item1->Item1->Item2->Item3->Item3->Item2->Item2->Item2->Item1->Item4" AS pathway 
    UNION ALL SELECT "Item1->Item1->Item1" AS pathway 
    UNION ALL SELECT "Item1->Item2->Item2" AS pathway 
) 
SELECT collapse_repeated(pathway) AS shorten_pathway, pathway 
FROM YourTable 

注意:同JS可以很容易地在傳統「翻譯」給JS UDF SQL

使用Window Functions傳統的SQL

SELECT GROUP_CONCAT_UNQUOTED(IF(repeats=1, item, CONCAT(item, "(x", STRING(repeats), ")")), "->"), pathway 
FROM (
    SELECT MIN(pos) AS ord, MIN(item) AS item, COUNT(1) AS repeats, pathway 
    FROM (
    SELECT item, pos, IFNULL(grp, 0)AS grp, pathway FROM (
     SELECT item, pos, SUM(change) OVER(PARTITION BY pathway ORDER BY pos ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS grp, pathway 
     FROM (
     SELECT item, pos, IF(item=next_item, 0, 1) AS change, pathway FROM (
      SELECT item, pos, LEAD(item) OVER(PARTITION BY pathway ORDER BY pos) AS next_item, pathway 
      FROM (
      SELECT item, POSITION(item) AS pos, pathway FROM (
       SELECT SPLIT(pathway, "->") AS item, pathway FROM 
       (SELECT "Item1->Item2->Item2->Item2->Item3->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item2->Item3->Item3->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item4" AS pathway), 
       (SELECT "Item1->Item2->Item2->Item3->Item1->Item1->Item1->Item2->Item3->Item3->Item2->Item2->Item2->Item1->Item4" AS pathway), 
       (SELECT "Item1->Item1->Item1" AS pathway), 
       (SELECT "Item1->Item2->Item2" AS pathway)    
      ) 
     ) 
     ) 
    ) 
    ) 
) 
    GROUP BY grp, pathway 
    ORDER BY ord 
) 
GROUP BY pathway 
1

我想說服自己,這是有可能只是通過數組操作(使用標準SQL),我想出了一個解決方案。解決該問題的另一種方法是使用分析功能,您可以在其中檢測路徑中項目的變化。

CREATE TEMPORARY FUNCTION PartsToString(
    parts_and_offsets ARRAY<STRUCT<part STRING, off INT64>>) AS ((
    SELECT 
    STRING_AGG(
     CONCAT(part_and_offset.part, 
      IF(parts_and_offsets[OFFSET(off + 1)].off - part_and_offset.off = 1, 
      "", 
      CONCAT("(x", CAST(parts_and_offsets[OFFSET(off + 1)].off - part_and_offset.off AS STRING), ")")))) 
    FROM UNNEST(parts_and_offsets) AS part_and_offset WITH OFFSET off 
    WHERE off + 1 < ARRAY_LENGTH(parts_and_offsets) 
)); 

CREATE TEMPORARY FUNCTION PathwayToParts(pathway STRING) AS ((
    SELECT 
    ARRAY_CONCAT(
     ARRAY_AGG(
     STRUCT(part, off)), 
     [STRUCT("" AS part, ARRAY_LENGTH(ANY_VALUE(parts)) AS off)]) AS parts_and_offsets 
    FROM (SELECT SPLIT(pathway, "->") AS parts), 
    UNNEST(parts) AS part WITH OFFSET off 
    WHERE off = 0 OR part != parts[OFFSET(off - 1)] 
)); 

WITH YourTable AS (
    SELECT "Item1->Item2->Item2->Item2->Item3->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item2->Item3->Item3->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item2->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item1->Item4" AS pathway 
    UNION ALL SELECT "Item1->Item2->Item2->Item3->Item1->Item1->Item1->Item2->Item3->Item3->Item2->Item2->Item2->Item1->Item4" AS pathway 
    UNION ALL SELECT "Item1->Item1->Item1" AS pathway 
    UNION ALL SELECT "Item1->Item2->Item2" AS pathway 
    UNION ALL SELECT "Item1->Item1->Item2" AS pathway 
    UNION ALL SELECT "Item1->Item2->Item3" AS pathway 
) 
SELECT PartsToString(PathwayToParts(pathway)) AS parts_string 
FROM YourTable; 
+0

是的,我知道這是你最喜歡的區域:o),所以我把它留給你。我仍然更喜歡JS UDF版本,因爲它最具可讀性和乾淨性,但無論如何,你的版本都是+1。順便說一句,這是我的內部用戶的問題,所以希望他們也會嘗試這個選項 –