webForumDet fria alternativet

REGEXP är detta samma sak?

Databaser & SQL

22 svar · 892 visningar · startad av LR^evil.sid

Medlem sedan maj 2002560 inlägg
Frågan#1

MySQL 5.1

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?

Medlem sedan maj 2002560 inlägg
#2

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:]]])*$'

Ger 218102 rader på 47.67 sek

Medlem sedan juni 20008 205 inlägg
#3

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?

Medlem sedan maj 2002560 inlägg
#4

REGEXP-strängen skall ersätta

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'

Medlem sedan juni 20008 205 inlägg
#5

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.

Medlem sedan maj 2002560 inlägg
#6

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å.

Medlem sedan juni 20008 205 inlägg
#7

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:]]])?$

Medlem sedan maj 2002560 inlägg
#8

REGEXP: AND LCASE(kunder.namn) NOT REGEXP '^[ah]b$|^[ah]b[[[:punct:]][[:space:]]]|[[:space:]]+[ah]b([[[:punct:]][[:space:]]])?$'
198790 rader mot 198777

får med regexp tillbaka 13 rader jag inte vill ha

Medlem sedan juni 20008 205 inlägg
#9

... som ser ut hur?

Medlem sedan maj 2002560 inlägg
#10

vet inte. hur jämnför jag det enklast? det är ju trots allt ca 200000 rader

EDIT, regexp träffar 2138 rader, WHERE NOT IN... skall fila på det

Medlem sedan maj 2002560 inlägg
#11

De raderna har ett bindestreck någonstans efter ab
ex:
Ab Härnösands Schakt- Och Trädg
Ab Nord-Emballage

Medlem sedan juni 20008 205 inlägg
#12

Va? Men de raderna borde du ju få fram även med icke-regexpvarianten.

Medlem sedan maj 2002560 inlägg
#13

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:]]]

Medlem sedan juni 20008 205 inlägg
#14

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

Medlem sedan maj 2002560 inlägg
#15

Det går inte att skilja ut AB/HB på annat sätt ur databasen som den ser ut nu och inga AB/HB skall vara med i urvalet

Medlem sedan juni 20008 205 inlägg
#16

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?

Medlem sedan maj 2002560 inlägg
#17

Ja det gör det, det verkar bara som att det är när ab följs av mellanslag eller punkt

Medlem sedan maj 2002560 inlägg
#18

Men om du anser det vara en bugg

spango skrev:

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:]]])?$';

Borde jag skriva en rapport till MySQL oxå?

Medlem sedan juni 20008 205 inlägg
#19

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.

Medlem sedan maj 2002560 inlägg
#20

får inte en etta, får en nolla

263 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
124 ms — deklarationer (db)
0 ms — hämta statistik (cache)
136 ms — hämta tråd, inlägg och bilagor (db)
123 ms — ändringar (db)