phpMyAdmin - mariaDB罗马数字函数

时间:2016-06-23 08:53:33

标签: function phpmyadmin xampp mariadb roman-numerals

任何人都可以帮助我完成我的排序功能 - 严重的是我不知道如何让它按照预期的方式工作。 :(数据库在Xampp的MariaDB中。我使用phpMyAdmin来执行查询。

DELIMITER $$

DROP FUNCTION IF EXISTS convRomanNumeral$$

CREATE FUNCTION convRomanNumeral (numeral CHAR(4))
  RETURNS INT
BEGIN
  DECLARE intnum INT;
    CASE numeral
      WHEN "I" THEN intnum = 1;
      WHEN "II" THEN intnum = 2;
    END CASE;
  RETURN intnum;
END;

$$

SET @iteration = -1;

UPDATE `st0gk_docman_documents` 
    SET created_on = DATE('2016-06-14') + INTERVAL(@iteration := @iteration + 1) SECOND
    WHERE `docman_category_id` = 141 ORDER BY convRomanNumeral(SUBSTRING(SUBSTRING_INDEX(title,'/',1),' ',-2) ASC, SUBSTRING_INDEX(title,'/',-2)+0 ASC;

所以我想要实现的是按标题对文档进行排序。示例标题是:

  • 文件Nr I / 36/2006
  • 文件Nr II / 36/2006
  • Document Nr I / 32/2006
  • 文件Nr II / 19/2006

按第一个罗马数字排序,然后按第二个阿拉伯数字排序后,我想更新日期。以下代码仅通过第二个阿拉伯数字更新正常工作:

SET @iteration = -1;

UPDATE `st0gk_docman_documents` 
    SET created_on = DATE('2016-06-14') + INTERVAL(@iteration := @iteration + 1) SECOND
    WHERE `docman_category_id` = 141 ORDER BY SUBSTRING_INDEX(title,'/',-2)+0 ASC;

我想使用CASE为罗马值返回适当的变量。我知道它并不完美,但我甚至无法使CASE和FUNCTION工作。我做错了什么?欢迎提出所有建议。

2 个答案:

答案 0 :(得分:0)

执行此操作的最佳方法是添加另一列,该列具有该字符串的可排序等效项。并且在插入表之前使用非SQL代码来解析和构建该列

答案 1 :(得分:0)

我做的第一个错误就是试图立即执行整个查询......在第一个小屋出来后,调试似乎更简单了。 :d

所以我创建了我的case函数来转换罗马数字:

DELIMITER $$

DROP FUNCTION IF EXISTS convRomanNumeralSubFunction$$
CREATE FUNCTION convRomanNumeralSubFunction (numeral CHAR(1))
  RETURNS INT
BEGIN
  DECLARE intnum INT;
    CASE numeral
      WHEN "I" THEN SELECT 1 INTO intnum;
      WHEN "X" THEN SELECT 10 INTO intnum;
      WHEN "C" THEN SELECT 100 INTO intnum;
      WHEN "M" THEN SELECT 1000 INTO intnum;
      WHEN "V" THEN SELECT 5 INTO intnum;
      WHEN "L" THEN SELECT 50 INTO intnum;
      WHEN "D" THEN SELECT 500 INTO intnum;
    END CASE;
  RETURN intnum;
END;

$$

之后我宣布了转换所需的第二个功能。我不知道你是否可以在函数内声明函数...而我并不想浪费更多时间在这上面。当然,您可以在Procedure中声明Function。无论如何。警告:此功能不能证明像IIX这样的BAD数字。这样的数字或将被严重计算。 AXI也不算数。

DELIMITER $$

DROP FUNCTION IF EXISTS convRomanNumeral$$
CREATE FUNCTION convRomanNumeral (numeral CHAR(10))
  RETURNS INT
BEGIN
  DECLARE currentintnum, previntnum, intnum, counter, numerallength INT;
  SET numerallength = LENGTH(numeral);
  SET counter = numerallength;
  SET intnum = 0;
  SET previntnum = 0;
  WHILE counter > 0 DO
      SET currentintnum = CAST(convRomanNumeralSubFunction(SUBSTRING(numeral,counter, 1)) as integer);
      IF currentintnum < previntnum THEN
        SET intnum = intnum - currentintnum;
      ELSE 
        SET intnum = intnum + currentintnum;
      END IF;
      SET previntnum = currentintnum;
      SET counter = counter - 1;
  END WHILE;
  RETURN intnum;
END;

$$

这就是它。现在您可以转换所有类型的罗马数字并对其进行排序。 用它来测试转换:

SELECT convRomanNumeral("XIX");

这是我最终使用的示例排序代码:

SET @iteration = -1;

UPDATE `st0gk_docman_documents` 
    SET created_on = DATE('2016-06-07') + INTERVAL(@iteration := @iteration + 1) SECOND
    WHERE `docman_category_id` = 67 ORDER BY convRomanNumeralBreak(SUBSTRING_INDEX(SUBSTRING_INDEX(title,'/',1),' ',-1)) ASC, SUBSTRING_INDEX(title,'/',-2)+0 ASC;

还有一件事 - 如果您试图在mySQL上执行此操作,那么您必须修复此行:

SET currentintnum = CAST(convRomanNumeralSubFunction(SUBSTRING(numeral,counter, 1)) as integer);

进入这个:

SET currentintnum = CAST(convRomanNumeralSubFunction(SUBSTRING(numeral,counter, 1)) as SIGNED);

这段代码可以改进,但正如@Rick James所说,这应该以不同的方式完成 - 不是作为db update而是在不同的表结构和排序机制中。