2016-10-16 2 views
0
  • La motivation ici était de générer facilement et avec précision des échantillons de données pour le nested ranges challenge.

Une table contient une seule colonne de type texte. Le texte contient une ou plusieurs lignes où chaque ligne contient une ou plusieurs sections créées à partir de lettres. Le but est d'écrire une requête qui renvoie un tuple pour chaque section avec son point de départ, son point final et sa valeur.SQL/REGEX puzzle/challenge Comment convertir des gammes d'art ASCII avec plusieurs caractères en données relationnelles?


échantillon de données

create table t (txt varchar (1000)); 

insert into t (txt) values 
(
' 
AAAAAAAAAAAAAAAAAAAAAAAAAAAA BBBB CCCCCCCCCCCCCCCCCCCCCCCCC 
DDDE FFFFFFFF GGGGGGGGG    HHHHHHHH IIIIIII 
JJ  KKKLLL  MM NN        OOOOO 
      P            QQ 
' 
) 
; 

résultats demandés

* Seules les 3 dernières colonnes (Début/fin/val) sont nécessaires, le reste sont des fins de débogage.

line_ind section_ind section_length section_start section_end section_val 
1   1    28    1    28   A 
1   2    4    31    34   B 
1   3    25    39    63   C 
2   1    3    1    3    D 
2   2    1    4    4    E 
2   3    8    7    14   F 
2   4    9    19    27   G 
2   5    8    43    50   H 
2   6    7    55    61   I 
3   1    2    1    2    J 
3   2    3    9    11   K 
3   3    3    12    14   L 
3   4    2    22    23   M 
3   5    2    25    26   N 
3   6    5    57    61   O 
4   1    1    13    13   P 
4   2    2    60    61   Q 

Répondre

0

Teradata

  • Actuellement regexp_split_to_table ne semble pas soutenir l'expression de longueur nulle (je l'ai créé l'incident RECGZJKZV). Afin de surmonter cette limitation, j'utilise regexp_replace pour pousser l'espace entre des séquences de lettres adjacentes, par ex. KKKLLL

with  l 
      as 
      (
       select  line_ind 
          ,line 

       from  table 
          (
           regexp_split_to_table (-1,t.txt,'\r','') 
           returns (minus_one int,line_ind int,line varchar(1000)) 
          ) 
          as l 
      ) 

select  l.line_ind 
      ,r.section_ind           
      ,char_length  (r.section)         as section_length 
      ,regexp_instr (l.line,'(\S)\1*',1,r.section_ind,0)  as section_start 
      ,regexp_instr (l.line,'(\S)\1*',1,r.section_ind,1) - 1 as section_end 
      ,substr   (r.section,1,1)        as section_val 

from  table 
      (
       regexp_split_to_table (l.line_ind,regexp_replace (l.line,'(?<=(?P<c>.))(?!(?P=c))',' '),'\s+','') 
       returns (line_ind int,section_ind int,section varchar(1000)) 
      ) 
      as r 
      ,l 

where  l.line_ind = 
      r.line_ind 

order by l.line_ind 
      ,r.section_ind 
; 

Oracle

select  regexp_instr (txt,'(\S)\1*',1,level,0)  - instr (txt,chr(10),regexp_instr (txt,'(\S)\1*',1,level,0) - length (txt) - 1,1) as section_start 
      ,regexp_instr (txt,'(\S)\1*',1,level,1) - 1 - instr (txt,chr(10),regexp_instr (txt,'(\S)\1*',1,level,0) - length (txt) - 1,1) as section_end 
      ,regexp_substr (txt,'(\S)\1*',1,level,'',1)                      as section_val 

from  t 

connect by level <= regexp_count (txt,'(\S)\1*') 
;