MySQL - 为自定义排序创建用户定义的函数

时间:2012-02-18 07:01:23

标签: mysql

我正在使用大量遗留数据(从平面文件数据库转换),其中字段格式化为输入记录的年份的最后2位数字,然后是4位数字增量。

例如,1998年创建的第三条记录为“980003”,2004年创建的第11条记录为“040011”。

我无法改变这些价值观 - 它们通过公司存在,在州,客户等处注册。我知道将年份和其余部分分成不同的列是很好的,但这不是可能。我甚至不能“内部”执行它,因为每行有大约300个可以排序的字段,并且他们非常习惯使用此字段作为记录标识符。

所以我正在尝试实现MySQL UDF(第一次)进行排序。查询执行成功,它允许我“通过custom_sort(无论如何)从表顺序中选择任何内容”,但顺序不是我所期望的。

以下是我正在使用的内容:

DELIMITER //

CREATE FUNCTION custom_sort(id VARCHAR(8))
    RETURNS INT
    READS SQL DATA
    DETERMINISTIC
    BEGIN
        DECLARE year VARCHAR(2);
        DECLARE balance VARCHAR(6);
        DECLARE stringValue VARCHAR(8);
        SET year = SUBSTRING(0, 2,  id);
        SET balance = SUBSTRING(2, 6, id);
        IF(year <= 96) THEN
            SET stringValue = CONCAT('20', year, balance);
        ELSE
            SET stringValue = CONCAT('19', year, balance);
        END IF;
        RETURN CAST(stringValue as UNSIGNED);
    END//

记录只能回到96(因此任意“如果前2个字符小于96,则前缀'20'否则前置'19'。。我对这一点并不感到兴奋,但不相信那个核心问题在哪里。

为了投入另一把扳手,事实证明1996年和1997年都是5位数,遵循上述相同的模式,而不是4位数增量,它是3位数的增量。同样,我怀疑这将是一个问题,但不是核心问题。

我使用此custom_sort获得的回报示例:

001471
051047
080628
040285
110877
020867
090744
001537
051111
080692
040349
110941
020931
090808
001603
051175

我真的不知道我在这里做了什么,并且从来没有将MySQL用于这样的UDF - 任何帮助都会受到赞赏。

TYIA

/编辑错字

/编辑2 concat需要“年”增值 - 仍然得到相同的结果

1 个答案:

答案 0 :(得分:5)

您的子字符串存在一些问题,最后转换为int会使其在结尾处使用更多数字排序值,而不是按年份。这应该会更好;

DELIMITER //

CREATE FUNCTION custom_sort(id VARCHAR(8))
    RETURNS VARCHAR(10)
    READS SQL DATA
    DETERMINISTIC
    BEGIN
        DECLARE year VARCHAR(2);
        DECLARE balance VARCHAR(6);
        DECLARE stringValue VARCHAR(10);
        SET year = SUBSTRING(id, 1, 2);
        SET balance = SUBSTRING(id, 3, 6);
        IF(year <= 96) THEN
            SET stringValue = CONCAT('20', year, balance);
        ELSE
            SET stringValue = CONCAT('19', year, balance);
        END IF;
        RETURN stringValue;
    END//

DELIMITER ;

这可以简化一点;

DELIMITER //

CREATE FUNCTION custom_sort(id VARCHAR(8))
    RETURNS varchar(10)
    DETERMINISTIC
    BEGIN
        IF(SUBSTRING(id, 1, 2) <= '96') THEN
            RETURN CONCAT('20', id);
        ELSE
            RETURN CONCAT('19', id);
        END IF;
    END//

DELIMITER ;