任何人都可以帮助我完成我的排序功能 - 严重的是我不知道如何让它按照预期的方式工作。 :(数据库在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;
所以我想要实现的是按标题对文档进行排序。示例标题是:
按第一个罗马数字排序,然后按第二个阿拉伯数字排序后,我想更新日期。以下代码仅通过第二个阿拉伯数字更新正常工作:
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工作。我做错了什么?欢迎提出所有建议。
答案 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而是在不同的表结构和排序机制中。