我被要求包含一个字段ComNo,如果Comment的字段长度大于5个字符,则Comment中的其余字符应出现在下一行中,而ComNo字段应该增加一个
输入
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查询实现相同的吗?
答案 0 :(得分: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产品则不需要)。注意:dbms_lob.substr()
与通常的substr()
函数相比,“amount”和“offset”(第二个和第三个参数)相反;请注意,当您比较解决方案时。
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
;
答案 1 :(得分: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
...
答案 2 :(得分: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
来创建其他行。