如果字段长度大于 n,则自动递增计数器
Auto increment counter if field length is greater than n
我被要求包含一个字段ComNo,如果Comments的字段长度大于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 查询来实现吗?
一个蛮力选项是 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
...
这是一种方法:
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
.
来创建额外的行
这是一个不预先假设评论长度的解决方案。我添加了两个字符串,一个短(少于 5 个字符)和一个长于 10 个字符,以及一个带有 NULL 注释以确保该行没有丢失,以彻底测试解决方案。
我假设 (empid, dt)
是基础 table 中的唯一组合(可能是主键)。顺便说一下,我希望您实际上没有在架构中使用 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数据类型,最好使用substr
的dbms_lob
版本。此外,如果必须将数据分成 75 个字符段,则必须调整几个数字。这是相同的解决方案,进行了这两项更改并且没有 ORDER BY 子句(如果用于将数据迁移到另一个数据库产品则不需要)。注意: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
;
我被要求包含一个字段ComNo,如果Comments的字段长度大于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 查询来实现吗?
一个蛮力选项是 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
...
这是一种方法:
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
.
这是一个不预先假设评论长度的解决方案。我添加了两个字符串,一个短(少于 5 个字符)和一个长于 10 个字符,以及一个带有 NULL 注释以确保该行没有丢失,以彻底测试解决方案。
我假设 (empid, dt)
是基础 table 中的唯一组合(可能是主键)。顺便说一下,我希望您实际上没有在架构中使用 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数据类型,最好使用substr
的dbms_lob
版本。此外,如果必须将数据分成 75 个字符段,则必须调整几个数字。这是相同的解决方案,进行了这两项更改并且没有 ORDER BY 子句(如果用于将数据迁移到另一个数据库产品则不需要)。注意: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
;