Sitter å kikar på en gammal SQL-fråga för att sålla ut icke önskvärda poster i ett urval och tänkte att det där måste kunna göras smidigare med REGEXP.
Till frågan, Är detta:
AND NOT LCASE(RIGHT(kunder.namn,4))=' ab.'
AND NOT LCASE(RIGHT(kunder.namn,4))=' hb.'
AND NOT LCASE(RIGHT(kunder.namn,3))=' ab'
AND NOT LCASE(RIGHT(kunder.namn,3))=' hb'
AND NOT LCASE(LEFT(kunder.namn,3))='hb.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab '
AND NOT LCASE(LEFT(kunder.namn,3))='hb '
AND NOT LCASE(kunder.namn)='ab'
AND NOT LCASE(kunder.namn)='hb'
samma sak som
AND NOT LCASE(kunder.namn) REGEXP '[ ][ab][.]{0,}$|[ ][hb][.]{0,}$|^[ab][.]{0,}|^[hb][.]{0,}|^[ab][ ]{0,}|^[hb][ ]{0,}|^[ab]$|^[hb]$|'
strukturerat
AND NOT LCASE(kunder.namn) REGEXP '[ ][ab][.]{0,}$|
[ ][hb][.]{0,}$|
^[ab][.]{0,}|
^[hb][.]{0,}|
^[ab][ ]{0,}|
^[hb][ ]{0,}|
^[ab]$|
^[hb]$|'
Går det att göra med en kortare REGEXP sträng? Hur skulle den se ut i så fall?
Det kunde vi ju snabbt konstatera att det _inte_ var.
Har fortsatt pilla och kommit fram till detta:
AND LCASE(kunder.namn) NOT REGEXP '^[ah]b$|[[:space:]]{1}[ah]b([[[:punct:]][[:space:]]])*$'
vilket get ett resultat på 218153 rader på 49.81 sek
medan
AND NOT LCASE(RIGHT(kunder.namn,4))=' ab.'
AND NOT LCASE(RIGHT(kunder.namn,4))=' hb.'
AND NOT LCASE(RIGHT(kunder.namn,3))=' ab'
AND NOT LCASE(RIGHT(kunder.namn,3))=' hb'
AND NOT LCASE(LEFT(kunder.namn,3))='hb.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab '
AND NOT LCASE(LEFT(kunder.namn,3))='hb '
AND NOT LCASE(kunder.namn)='ab'
AND NOT LCASE(kunder.namn)='hb'
ger ett resultat på 218139 rader på 47.78 sek
Tips på hur jag kommer åt de 14 sista raderna?
EDIT
AND LCASE(kunder.namn) NOT REGEXP '^[ah]b([[[:punct:]][[:space:]]])*|^[ah]b$|[[:space:]]{1}[ah]b([[[:punct:]][[:space:]]])*$'
Exakt vad är det tänkt att regexpen ska matcha? Får inte riktigt grepp om saken. Att strängen inte får innehålla "ab" eller "hb" på vissa ställen förstår jag, men i vilka sammanhang? Kan du ge exempel?
AND NOT LCASE(RIGHT(kunder.namn,4))=' ab.'
AND NOT LCASE(RIGHT(kunder.namn,4))=' hb.'
AND NOT LCASE(RIGHT(kunder.namn,3))=' ab'
AND NOT LCASE(RIGHT(kunder.namn,3))=' hb'
AND NOT LCASE(LEFT(kunder.namn,3))='hb.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab '
AND NOT LCASE(LEFT(kunder.namn,3))='hb '
AND NOT LCASE(kunder.namn)='ab'
AND NOT LCASE(kunder.namn)='hb'
Ja, så långt är jag med, men ärligt talat orkar jag inte sätta mig ner och grunna på exakt vilka strängar som matchar det där och vilka som inte gör det. Har du lust att, med egna ord och inte kod, förklara vad det är du vill göra? :) Anledningen till varför jag tjatar är för att jag tror att det går att optimera rätt rejält genom att ersätta det med en regexp som inte gör exakt samma sak men som ger samma resultat.
ur urvalet sålla bort alla stängar som:
* är exakt ab el. hb
* börjar med ab följt av mellanslag
* börjar med ab följt av punkt
* börjar med hb följt av mellanslag
* börjar med hb följt av punkt
* slutar med mellanslag följt av ab
* slutar med mellanslag följt av hb
* slutar med mellanslag följt av ab följt av punkt
* slutar med mellanslag följt av hb följt av punkt
testade
'^[ah]b$'
mot
AND NOT LCASE(kunder.namn)='ab'
AND NOT LCASE(kunder.namn)='hb'
Det gav samma resultat : ) så jag antar att den delen är avklarad.
testade
^[ah]b([[[:punct:]][[:space:]]])*
mot
AND NOT LCASE(LEFT(kunder.namn,3))='hb.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab.'
AND NOT LCASE(LEFT(kunder.namn,3))='ab '
AND NOT LCASE(LEFT(kunder.namn,3))='hb '
199160 mot REGEXP's 199107
testade
[[:space:]]+[ah]b([[[:punct:]][[:space:]]])*$
mot
AND NOT LCASE(RIGHT(kunder.namn,4))=' ab.'
AND NOT LCASE(RIGHT(kunder.namn,4))=' hb.'
AND NOT LCASE(RIGHT(kunder.namn,3))=' ab'
AND NOT LCASE(RIGHT(kunder.namn,3))=' hb'
Det gav samma resultat : ) så jag antar att den delen är avklarad också.
OK, så mycket för mina optimeringsplaner :) ^[ah]b([[[:punct:]][[:space:]]])* strular på grund av stjärnan. Nu är den regexpen faktiskt ekvivalent med ^[ah]b, läser man ut den blir det "börjar med ett 'a' eller 'h', som följs av 'b', som följs av noll eller fler mellanslag och/eller punkter". Av samma anledning kanske du vill byta ut stjärnan i sista regexpen mot frågetecken (så att det blir "en eller ingen punkt" istället för "noll eller flera punkter"). Inte strikt nödvändigt, men nu matchar den exempelvis även "fubar ab.." också.
Jag tror att det här borde klara biffen: ^[ah]b$|^[ah]b[[[:punct:]][[:space:]]]|[[:space:]]+[ah]b([[[:punct:]][[:space:]]])?$
REGEXP: AND LCASE(kunder.namn) NOT REGEXP '^[ah]b$|^[ah]b[[[:punct:]][[:space:]]]|[[:space:]]+[ah]b([[[:punct:]][[:space:]]])?$'
198790 rader mot 198777
Kollade lite noggrannare och bindestrecket har inte med saken att göra
13 rader:
Ab.
Ab Nord-Emballage
Ab Härnösands Schakt- Och Trädg
Ab Härnösands Schakt- Och Trädg
Ab Härnösands Schakt- Och Trädg
Ab Härnösands Schakt- Och Trädg
Ab Härnösands Schakt- Och Trädg
Ab Emil Lundgrens Bil- Och
Ab Emil Lundgrens Bil- Och
Ab Finskören
Ab Previa
Ab T Wasserman
Ab T Wasserman
antar att denna inte fungerar som den skall: ^[ah]b[[[:punct:]][[:space:]]]
Men varför vill du inte ha de här raderna? Det ser mer som en bugg i nonregexpvarianten att de inte kom med, än att det är en bugg i regexpen som gör att de kommer med. :q
Ah, såklart, det var bara jag som tänkte fel. Tänkte att det var "WHERE strängen REGEX mönstret" och inte "WHERE strängen NOT REGEX mönstret" :r
Men det är ett skumt fel. Lyckas den sortera bort några poster som börjar på "Ab" alls?
Det ser mer som en bugg i nonregexpvarianten att de inte kom med, än att det är en bugg i regexpen som gör att de kommer med.
Så får WHERE-klasulen se ut så här då.
AND NOT LCASE(LEFT(kunder.namn, 3)) = 'ab '
AND NOT LCASE(LEFT(kunder.namn, 3)) = 'ab.'
AND LCASE(kunder.namn) NOT REGEXP '^[ah]b$|^[ah]b[[[:punct:]][[:space:]]]|[[:space:]]+[ah]b([[[:punct:]][[:space:]]])?$';
Det som är mest sannolikt att lida av en bugg i den här tråden är nog min hjärna, är jag rädd ;)
Fast testa att köra typ SELECT 'Ab Previa' REGEXP '^[ah]b[[[:punct:]][[:space:]]]' och se om det ger en etta som svar. Gör det inte det är något fel, antingen på hur vi förstått regexp-syntaxen, eller på regexpmotorn. Får du däremot tillbaka en etta är något fel på hur regexpen sätts samman med de andra bitarna.