0
votes

Extraire si la chaîne contient des numéros motif

J'ai une colonne dans mon jeu de données où je veux extraire les chiffres dans un emplacement spécifique uniquement si strong> la structure de la chaîne contient # - # code>.

Comment j'écrirais cela dans SQL (écrire dans le flocon de neige actuellement)? p>

Exemple: P>

CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 4) ELSE NULL END Number1
CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 5) ELSE NULL END Number2
CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 6) ELSE NULL END Number3
CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 7) ELSE NULL END Number4


6 commentaires

Quel type de SQL?


La documentation de flocon de neige dit "ANSI"


Vous voulez donc les chiffres s'il y a au moins 3 numéros de séquence ... peu importe le nombre de chaînes? Que se passe-t-il si les chiffres sont séparés par une chaîne comme A-B-1-2-Z-3?


Ensuite, cela ne fonctionne pas, doit être comme ceci: # - # - #


Étant donné que les séquences numériques commencent à différentes parties pour différentes colonnes A , vous ne pouvez pas extraire les numéros avec les constantes 4-7.


Pour ceux qui contiennent les 3 chiffres d'une rangée, il commence toujours à la 4ème position


3 Réponses :


1
votes

Je pense que votre comme code> expression est trop large. Vous pouvez le réduire avec une correspondance de regex, comme: xxx pré>

la réégycle correspond à 3 groupes de chiffres consécutifs séparés par des tirets et précédent par un tiret (ou situé au début de la chaîne). , ou suivi d'un tiret (ou situé à la fin de la chaîne). p>

Ceci peut également être orthographié: P>

CASE 
    WHEN COLUMN_A RLIKE '.*(^|-)\\d+-\\d+-\\d+($|-).*' 
    THEN SPLIT_PART(COLUMN_A, '-', 4) 
    ELSE NULL 
END Number1


15 commentaires

Pas de chance avec cela, je l'ai essayé sur cette chaîne spécifique: ABC-Acrobat-Owl-23020365-255738062-451886974-121804749


Toutes mes valeurs sont capitalisées, cela fait-il une différence?


@ NAK5120: Cette chaîne devrait correspondre à la regex. Qu'est-ce que vous obtenez si vous faites quelque chose comme: Sélectionnez cas lorsque 'ABC-Acrobat-Owl-23020365-255738062-451886974-451886974-451886974-121804749' RLIME '^ [A-ZA-Z] + - [A-ZA-Z] + - [a-za-z] + - \ d + - 'puis 1 autre 0 fin : 0 ou 1?


Je reçois 0 malheureusement


D'ACCORD. Et si vous utilisez cette regex à la place: '^ [A-ZA-Z] + - [A-ZA-Z] + - [A-ZA-Z] + - [0-9] + -' ?


même chose, je reçois un 0


De plus, je recherche 3 numéros connectés par un tiret, pas des caractères alphabétiques. Mais je pense qu'une fois que la fondation est incluse, je pouvais juste faire quelque chose comme ^ [0-9] + - [0-9] + - [0-9]


@ NAK5120: OK Modifions l'approche alors. Peut-être quelque chose comme '\ b \ d + - \ d + - \ d + \ b' ? Correspond-il à votre chaîne?


Nope, c'est ce que j'ai fait: Sélectionnez cas lorsque 'ABC-Acrobat-Owl-23020365-255738062-451886974-451804749' RLIT '' \ B \ D + - \ D + - \ D + \ B 'puis 1 autre 0 fin < / code> résultat = 0


'(^ | -) \ d + - \ d + - \ d + ($ | -)' ?


Pas de chance, essayé ceci: Sélectionnez cas lorsque 'ABC-Acrobat-howg-23020365-255738062-451886974-451804749' RLITE '(^ ​​| -) \ D + - \ D + - \ D + ($ | -)' Alors 1 Sinon 0 fin


Le type de données de la chaîne est: varchar (16777216)


Laissez-nous Continuer cette discussion en chat .


S'il vous plaît rappelez-vous que le caractère spécial \ dans le flocon de neige regexps doit être échappé pour une analyse générale de la chaîne, de sorte que la chaîne REGEXP pour correspondre à un chiffre est '\\ d'


@Hanshenrikeriksen: ah oui ... Maintenant que vous dites que cela semble si évident. Je comprends maintenant pourquoi certaines de mes tentatives échouaient. Merci pour le rappel, j'ai mis à jour ma réponse en conséquence!



0
votes

Je n'ai pas de flocon de neige sur la main, mais quelque chose comme ça devrait fonctionner: Voici l'approche suggérée: diviser la chaîne en une table, énumérer les chiffres, puis utiliser l'agrégation conditionnelle.

Je n'ai pas de flocon de neige sur la main pour tester, mais quelque chose comme ceci: p>

select column_a,
       max(case when seqnum = 1 then value end) as number_1,
       max(case when seqnum = 2 then value end) as number_2,
       max(case when seqnum = 3 then value end) as number_3,
       max(case when seqnum = 4 then value end) as number_4
from (select t.column_a, s.*,
             row_number() over (partition by (case when s.value rlike '^[0-9]+$'
                                                   then 1 else 0
                                              end)
                                              order by s.index
                               ) as seqnum
      from t cross join lateral
           split_to_table(t.column_a, '-') s
     ) t
group by column_a;


3 commentaires

Merci Gordon, mais je cherche à éviter les jointures. Quelque chose comme la réponse précédente serait parfait parce que j'ai d'autres règles qui se produisent à part cela


@ nak5120. . . Cela fait ce que vous voulez et travaillez généralement pour toutes les colonnes. Cela semble être la réponse à la question que vous avez posée.


J'ai exécuté le code ci-dessus et il ne semble pas produire le résultat correct. Pour une, toutes les 1er pièces texte (ABC, ABC, JEN, LOE) de colonne_a sont rapportées en tant que chiffres. Il n'y a pas non plus de code pour assurer qu'il y a au moins 3 numéros consécutifs.



1
votes

Je ne suis pas sûr de savoir pourquoi la "réponse correcte" actuelle est marquée comme telle, car elle ne sélectionne pas les lignes correctes, elle n'extrait pas le résultat de manière particulièrement utile.

La requête suivante fournit le bon Réponse en extrayant d'abord une sous-chaîne avec au moins 3 numéros consécutifs, puis extraire le nième numéro de cette sous-chaîne de 3 numéros de 3+: xxx


0 commentaires