Problembeschreibung/Zielstellung

Mitunter kommt es vor, dass man in einer MySQL-Tabelle varchar()-Datenfelder hat in denen Informationen stehen an die man herankommen möchte, z.B. um gezielt eine korrekte numerische Sortierung zu erreichen.

So können z.B. in Artikelnummern oder Matchcodes an irgend einer Stelle eine Information zu einem Produktdurchmesse kodiert sein. Nehme wir mal als Beispiel ein DIN-Normteil. Eine Artikelnummer oder ein Matchcode könnte z.B. so aussehen: DIN9861 0,5 71 D-HSS. An zweiter Stelle sehen wir hier unseren Durchmesser, an 3. Stelle eine Längenangabe.

Das Problem stellt sich jetzt in zwei Stufen da: Zum einen müssen wir die Stellen separieren an denen unsere Dimensionsagaben stehen, dann müssen diese von einem String in einen numerischen Wert umgewandelt werden, damit die darauf basierende Sortierung korrekt numerisch und eben nicht alphanumerisch erfolgt.

 



 

 

Umsetzung im Detail

Bei nachfolgendem Beispiel wollen wir aus dem Matchcode (mc) den Durchmesser ermitteln. Das erfolgt zunächst durch MySQL-Stringfunktionen und der nachfolgenden Typumwandlung.

  • Mit LOCATE() finden wir das Vorkommen von Leerzeichen als Informationstrenner
  • In diesem Fall mit SUBSTR() holen wir uns ein Anzahl von Zeichen (Klappt nur, wenn diese so exakt bekannt sind, sonst muss man auch das Ende wieder mit LOCATE() ermitteln.).
  • Mit RTRIM() entfernen wir überflüssige Zeichen
  • Mit REPLACE() tauschen wir das störende Dezimalkomma gegen eine Dezimalpunkt aus, so wie es MySQL für unsere Umwandlungsfunktion CAST() erwartet.
  • CAST() wandelt schließlich durch Angabe von DECIMAL(5,2) in das gewünschte Dezimalformat um (Manchmal liest man auch FLOAT statt DECIMAL(), jedoch funktioniert das bei mir nicht.).

Ein fertiger einfacher MySQl-Query könnte dann z.B. so aussehen:

SELECT mc,
CAST(REPLCE(RTRIM(SUBSTR(mc,LOCATE(' ',mc)+1,4)),',','.') as DECIMAL(5,2)) AS Dm
FROM _webcatalog_vm
WHERE art_grp LIKE 826
GROUP BY Dm
ORDER BY Dm
;

Mit dieser Abrage steht dann wirklich der DS mit dem Dm 19.00 nach dem mit dem Dm 2.00.

Hier als Alternative mal eine Abfrage ohne bekannte Stringlänge für die Dm-Angabe:

SELECT
  mc,
  CAST(
    REPLACE(
      SUBSTR(
        mc, # String
        LOCATE(' ', mc)+1, # ab Pos.
        LOCATE(' ', mc, LOCATE(' ',mc)+1 ) - LOCATE(' ', mc)-1
      )
      ,','
      ,'.'
    )
    AS DECIMAL(5,2)
  ) AS Dm
FROM _webcatalog_vm
WHERE art_grp LIKE 826
GROUP BY Dm
ORDER BY Dm
;