2010-04-30 22 views
8

Bir tablonun dize sütunundan bir sözcük çıkarmak istiyorum.mysql'deki REGEXP_SUBSTR karşılığı nedir?

description 
=========================== 
abc order_id: 2 xxxx yyy aa 
mmm order_id: 3 nn kk yw 

Beklenen sonuç en fazla 100 satır sahip olan en

order_id 
=========================== 
2 
3 

Tablo, metin uzunluğu ~ 256 char ve kolon, her zaman bir order_id mevcut bulunmaktadır

ayarlayın. Yani performans bir sorun değil.

Oracle'da bu sorun için REGEXP_SUBSTR'u kullanabilirim. Bunu MySQL'de nasıl çözerim?

Ben sorunu çözmek için LOCATE kullanarak ve SUBSTR am 1

Düzen. Kod çirkin. Kodu yazdıktan on dakika sonra, böyle çirkin bir kod yazan adamı lanetliyorum.

REGEXP_SUBSTR işlevini MySQL belgelerinde bulamadım. Ama ben bunun var olduğunu umuyorum ..

Yanıt: Tablo neden optimize edilemiyor? Veriler neden bu kadar aptalca saklanıyor?

Verdiğim örnek, yalnızca çözmeye çalıştığım sorunu gösterir. Gerçek senaryoda, zaman uyumsuz görevleri yürütmek için bir DB tabanlı 3. parti kuyruk yazılımı kullanıyorum. Sıra, Ruby nesnesini metin olarak serileştirir. Tablo yapısı VEYA veri formatı üzerinde hiçbir kontrolüm yok. Sıradaki görevler yinelenebilir. Test kurulumumuzda, eski verilerden dolayı yinelenen görevlerden bazıları başarısız oluyor. Hatayı önlemek için bu görevleri silmem gerekiyor. Bu tür hatalar yaygın değildir, dolayısıyla normalize bir gölge tablosu korumak istemiyorum.

cevap

3

Konerak'ın dediği gibi, MySql'de REGEXP_SUBSTR eşdeğeri yoktur. Sen SUBSTRING mantığı kullanarak gerekenleri yapabilirdi, ama bu çirkin:

SELECT 
    SUBSTRING(lastPart.end, 1, LOCATE(' ', lastPart.end) - 1) AS orderId 
FROM 
    (
    SELECT 
     SUBSTRING(dataset.description, LOCATE('order_id: ', dataset.description) + LENGTH('order_id: ')) AS end 
    FROM 
     (
     SELECT 'abc order_id: 2 xxxx yyy aa' AS description 
     UNION SELECT 'mmm order_id: 3 nn kk yw' AS description 
     UNION SELECT 'mmm order_id: 1523 nn kk yw' AS description 
    ) AS dataset 
    ) AS lastPart 

Düzenleme: Sen MySql

yılında
SELECT 
    PREG_CAPTURE('/.*order_id:\s(\d+).*/', dataset.description,1) 
FROM 
    (
    SELECT 'abc order_id: 2 xxxx yyy aa' AS description 
    UNION SELECT 'mmm order_id: 3 nn kk yw' AS description 
    UNION SELECT 'mmm order_id: 1523 nn kk yw' AS description 
) AS dataset 
+1

Yaptığım şey bu. Bunu yazmak için zaman ayırın +1 –

+1

LENGTH() yerine CHAR_LENGTH() işlevini kullanmak için düzenlenmiş yanıt, ikincinin boyutu, dizenin uzunluğunu değil Bayt cinsinden döndürür. Örneğin, UTF8 ile sorun yaşayacaksınız –

1

MySQL eşdeğeri yoktur. MySQL REGEXP dizeleri eşleştirmek için kullanılabilir, ancak dönüştürmek için kullanılamaz.Saklanmış yordamlarla ve çok sayıda REPLACE/SUBSTRING mantığıyla çalışmayı deneyebilir veya programlama dilinizde yapabilirsiniz - bu en kolay seçenek olmalıdır.

Veri biçiminizin iyi seçilmiş olduğundan emin misiniz? Eğer order_id'e ihtiyacınız varsa, onu farklı bir sütunda saklamak mantıklı olmaz, böylece indeksler ekleyebilir, birleştirmeler ve beğeniler kullanabilirsiniz?

+1

veri formatı. Örneğin, veri geçişi gerçekleştirirken veya başka bir sistemden bir şeyler ithal ederken, verdiğimiz şeyleri sık sık ele almak zorundayız. – APC

+0

Güncellenmiş sorumu, neden böyle bir veriye sahip olduğumu açıkla. –

0

veya sizinle regex Perl programının erişim sağlayan bu user defined function deneyebilirsiniz Bunu yapabilir ve çirkinliği kendiniz koruyabilirsiniz:

select SUBSTRING_INDEX(SUBSTRING_INDEX('habc order_id: 2 xxxx yyy aa',' ',3),' ',-1); 
İlgili konular