如果字段长度大于n,则自动递增计数器

时间:2016-10-05 02:06:41

标签: sql oracle auto-increment

我被要求包含一个字段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查询实现相同的吗?

3 个答案:

答案 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来创建其他行。