2016-10-05 15 views
3

我要求包含字段ComNo,如果字段長度超過5個字符,則Comment中的其餘字符應顯示在下一行,並且ComNo字段應該通過一個如果字段長度大於n,則自動增加計數器

輸入

EmpID EmpName ServiceNumber Date   Comments 
1  a  123   23-03-1990 wednesday 
1  a  1234   24-04-1990 Test12 
2  b  234   24-05-2016 Todayis 

遞增和預期輸出是

EmpID EmpName ServiceNumber Date  ComNo Comments 
1  a  123   23-03-1990 1  wedne 
1  a  123   23-03-1990 2  sday 
1  a  1234   24-04-1990 1  Test1 
1  a  1234   24-04-1990 2  2 
2  b  234   24-05-2016 1  Today 
2  b  234   24-05-2016 2  is 

我有一個想法如何實現這一點使用PLSQL過程但我們可以用sql查詢來實現嗎?

回答

2

這是一個解決方案,不會對評論的長度做任何事先假設。我添加了兩個字符串,一個短(少於5個字符),一個長於10個字符,另一個使用NULL註釋以確保行不會丟失,從而徹底測試解決方案。

我假設(empid, dt)是基表中的唯一組合(可能是主鍵)。順便說一句,我希望你實際上沒有在模式中使用Date作爲列名。

該解決方案不包含WITH子句;它始於select empid...也可能不需要ORDER BY子句。

with 
    test_data (empid, empname, servicenumber, dt, comments) as (
     select 1, 'a', 123, to_date('23-03-1990', 'dd-mm-yyyy'), 'wednesday' from dual union all 
     select 1, 'a', 1234, to_date('24-04-1990', 'dd-mm-yyyy'), 'Test12'  from dual union all 
     select 2, 'b', 234, to_date('24-05-2016', 'dd-mm-yyyy'), 'Todayis'  from dual union all 
     select 2, 'b', 235, to_date('25-05-2016', 'dd-mm-yyyy'), 'Joe'   from dual union all 
     select 3, 'c', 238, to_date('25-05-2016', 'dd-mm-yyyy'), ''   from dual union all 
     select 4, 'c', 2238, to_date('25-05-2016', 'dd-mm-yyyy'), 'longer string' from dual 
    ) 
select empid, empname, servicenumber, dt, level as comno, 
     substr(comments, 5 * level - 4, 5) as comments 
from test_data 
connect by level <= 1 + length(comments)/5 
    and prior empid = empid 
    and prior dt = dt 
    and prior sys_guid() is not null 
order by empid, dt 
; 

    EMPID E SERVICENUMBER DT    COMNO COMMENTS 
---------- - ------------- ---------- ---------- -------------------- 
     1 a   123 1990-03-23   1 wedne 
     1 a   123 1990-03-23   2 sday 
     1 a   1234 1990-04-24   1 Test1 
     1 a   1234 1990-04-24   2 2 
     2 b   234 2016-05-24   1 Today 
     2 b   234 2016-05-24   2 is 
     2 b   235 2016-05-25   1 Joe 
     3 c   238 2016-05-25   1 
     4 c   2238 2016-05-25   1 longe 
     4 c   2238 2016-05-25   2 r str 
     4 c   2238 2016-05-25   3 ing 

新增:如果你的數據是CLOB數據類型,最好是使用dbms_lob版本的substr。另外,如果您必須將數據切分爲75個字符,則必須調整多個數字。下面是相同的解決方案,這兩個更改沒有ORDER BY子句(如果用於將數據遷移到另一個db產品,則不需要)。注意:與通常的substr()函數相比,dbms_lob.substr()的「金額」和「偏移」(第二個和第三個參數)反轉;注意當你比較解決方案時。

select empid, empname, servicenumber, dt, level as comno, 
     dbms_lob.substr(comments, 75, 75 * level - 74) as comments 
from test_data 
connect by level <= 1 + length(comments)/75 
    and prior empid = empid 
    and prior dt = dt 
    and prior sys_guid() is not null 
; 
+0

謝謝:)它的工作原理 –

0

蠻力的辦法是隻UNION一起從一次分裂由5個字符的評論引起的記錄:

SELECT EmpID, EmpName, ServiceNumber, Date, 1, SUBSTR(Comments, 1, 5) AS Comments 
FROM yourTable 
UNION ALL 
SELECT EmpID, EmpName, ServiceNumber, Date, 2, SUBSTR(Comments, 6, 5) AS Comments 
FROM yourTable 
WHERE SUBSTR(Comments, 6, 5) <> '' -- but don't show a record if 
UNION ALL       -- all characters already used 
... 
+0

@AnnieJeba然後看看戈登的答案。順便說一句,你爲什麼需要這樣做? –

+0

http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions181.htm#SQLRF06114 – mathguy

+0

@mathguy爲什麼我認爲OP在使用Postgres? –

0

下面是做到這一點的一種方法:

with n as (
     select 1 as n from dual union all 
     select 2 from dual 
    ) 
select EmpID, EmpName, ServiceNumber, Date, ComNo, 
     substr(comments, n.n * 5 - 4, 5) as Comments 
from t join 
    n 
    on length(comments) >= n.n * 5 + 1; 

注意:您的示例只有最多10個字符的註釋,因此n只需要值1和2。您可以通過擴展n來創建其他行。

+0

嗨,戈登,謝謝你的回覆。我的示例只有最多10個字符的註釋,但實際數據的註釋超過4000個字符。 –

+0

@AnnieJeba。 。 。這種解決方案很容易擴展,以防萬一。但是,我注意到,Oracle將字符串限制爲4,000個字符,所以如果它們比這更長,我會感到驚訝。 –

+0

@GordonLinoff - CLOB數據類型的Oracle文檔:https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype。htm#i3237 – mathguy