2012-07-18 57 views
0

我在这个名为MM的列中有这个数字4.40-4.85X3.60。如何在mysql查询中复杂的数字之间进行搜索?

我想搜索器,可通过MySQL的更大或低于3点从每个编号为exampel号码:

[4.37-4.43] - ,之后[4.82-4.88] X [0-9]的数X可以是任何数字。

我试过使用正则表达式,但我没有找到真正有用的东西,请告知。

+0

哪些正则表达式不起作用?示例 – 2012-07-18 15:58:44

+1

'4.40-4.85X3.60'不是数字 – Shikiryu 2012-07-18 15:59:52

+0

正则表达式不是正确的选择,你最好使用sql字符串函数将列值分成三部分,然后检查这些值是否在范围内。 – 2012-07-18 16:01:13

回答

0

一种方法是将字符串“拆分”,以便从中获取所需的单独组件。假设该字符串总是使用“ - ”和“X”的三个组成部分,在此查询表达式分离将“拆分”它给你:

SELECT SUBSTRING_INDEX(@n,'-',1) AS s1 
    , SUBSTRING_INDEX(SUBSTRING_INDEX(@n,'-',-1),'X',1) AS s2 
    , SUBSTRING_INDEX(@n,'X',-1) AS s3 
    FROM (SELECT @n := '4.40-4.85X3.6') n 

然后可以在每次这些表达式转换为数值。

请注意,MySQL可能会(默默地)丢失精度数字,可能返回“0”表示无法转换为数字的字符串,或者MySQL可能会抛出异常或警告。

因此,请谨慎选择DECIMAL(m,n)的比例和精度,以避免溢出并正确处理舍入/截断。您示例中显示的所有数据都适合DECIMAL(3,2),但这仅仅是一个示例,并不是所有数据的保证。

我会在内联视图中执行“搜索参数”字符串的转换,然后将它加入到要搜索的表中。

事情是这样的:

SELECT t.MM 
    FROM mytable t 
    JOIN (SELECT CONVERT(SUBSTRING_INDEX(@n,'-',1)      ,DECIMAL(6,2)) AS s1 
      , CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(@n,'-',-1),'X',1),DECIMAL(6,2)) AS s2 
      , CONVERT(SUBSTRING_INDEX(@n,'X',-1)      ,DECIMAL(6,2)) AS s3 
      FROM (SELECT @n := '4.40-4.85X3.6') n 
     ) p 
    ON ABS(p.s1 - CONVERT(SUBSTRING_INDEX(t.MM,'-',1),DECIMAL(6,2))) 
     <= .03 
    AND ABS(p.s2 - CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(t,MM,'-',-1),'X',1),DECIMAL(6,2)) 
     <= .03 

连接谓词是距离搜索参数减去(衍生)数值从表中从(衍生)数值值,检查差异的问题。

同样,正如我之前提到的,在转换为DECIMAL操作的情况下,请注意字符串不是预期格式的问题,太大而不适合缩放(溢出)的值以及舍入/截断。你可能会得到意想不到的结果(MySQL可能会失去精度并且无声无息地伸缩,或者可能会抛出异常和/或警告。(行为取决于会话的sql_mode设置。)

2

对这三个数字使用单独的列,这将解决您的所有问题。

否则,使用类似:

WHERE 
    CAST(SUBSTR(MM FROM 1 FOR (@tmp1:=POSITION("-" IN MM))) AS DECIMAL(3,2)) 
     BETWEEN 4.37 AND 4.43 
    AND 
    CAST(SUBSTR(MM FROM @tmp1 FOR POSITION("X" IN MM)[email protected]) AS DECIMAL(3,2)) 
     BETWEEN 4.82 AND 4.88 

,但请记住,这对你可能对你的表的任何索引完全螺丝。

+0

将它分解为搜索'-'和'X'在字符串中的位置以及那三个部分然后检查(用'between')的部分会更好 - – 2012-07-18 16:05:27

+0

@Ωmega也许,我只是假设数字是定点的,但是如果它们是10或更高,那么它又会如何。好的,将会被编辑。 – 2012-07-18 16:07:37