2017-02-28 103 views
0

我有一个名为year varchar(100)的列表。此列可以包含像MySql仅选择数字并从varchar列中排列它们

Year 
------- 
1901 
    0 
circa 12580 
125d4 great 
year 1012 
3411 standard 
12 
    saf 
1234 

现在我想通过Year升序或在Year领域找到第4位下降到订单数据。我想:

  1. 仅获得这些列的有4个或多个数字(单独或与 一些字符串)
  2. 提取前4位数字(如果超过4个或一些整数)或获得4位数(如果列仅有4位值),基于上述两个条件

我想我的结果按升序排列设置像

  • 排序结果集:

    Year 
    1012 
    1234 
    1258 
    1901 
    3411 
    

    反之亦然按降序排列。

    我曾尝试以下操作:

    SELECT * 
    FROM table 
    WHERE YEAR REGEXP '^[0-9]+$' AND LENGTH(YEAR) = 4 
    ORDER BY CAST(YEAR AS UNSIGNED) DESC; 
    

    但这只会返回他们只有4个数字和订单列,但还不如我上面提到的结果。

  • +1

    最好的做法是创建与诠释一个新列年,并按此排序。您可能会成功建立一个查询来按提取的正则表达式进行排序,但它不会使用索引(如果有很多行,这很重要)。如果您的查询不是生产应用程序,您可以创建一个临时表,使用旧表中的所有行和规范化的年份值填充它,然后对其进行正常排序。 –

    +0

    @DanIonescu我现在正在生产,我现在不能创建列 –

    +1

    好的,所以查询是针对应用程序的,或者它只是一次分析数据的一次? –

    回答

    1

    这就是我解决问题的方法。我创建了一个存储功能,以帮助从here(从Ushastry回复),看起来像

    CREATE FUNCTION `get_numeric`(`year` VARCHAR(50)) RETURNS INT(11) 
          NO SQL 
         BEGIN 
          DECLARE ctrNumber VARCHAR(50); 
          DECLARE finNumber VARCHAR(50) DEFAULT ' '; 
          DECLARE sChar VARCHAR(2); 
          DECLARE inti INTEGER DEFAULT 1; 
           IF LENGTH(year) > 0 THEN 
            WHILE(inti <= LENGTH(year)) DO 
             SET sChar= SUBSTRING(year,inti,1); 
               SET ctrNumber= FIND_IN_SET(sChar,'0,1,2,3,4,5,6,7,8,9'); 
    
               IF ctrNumber > 0 THEN 
              SET finNumber=CONCAT(finNumber,sChar); 
               ELSE 
              SET finNumber=CONCAT(finNumber,' '); 
               END IF; 
             SET inti=inti+1; 
            END WHILE; 
            RETURN finNumber; 
           ELSE 
            RETURN 'Invalid'; 
           END IF; 
         END 
    

    然后下面的查询工作正常

    SELECT id, YEAR, SUBSTRING(`get_numeric`(YEAR),1,4) AS act_year FROM table HAVING LENGTH(act_year) = 4 ORDER BY act_year ASC; 
    
    相关问题