2016-06-23 5 views
-1

может кто-нибудь помочь мне с моей функцией сортировки - серьезно я не знаю, как я могу заставить его работать так, как предполагалось. . :(База данных находится в MariaDB в Xampp я использую PhpMyAdmin для выполнения запросаphpMyAdmin - mariaDB roman numals function

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
  • Документ 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. Что я делаю неправильно? Все предложения приветствуются.

ответ

0

Первая ошибка, которую я делал, заключалась в том, что она пыталась выполнить весь запрос сразу ... После того, как первая ложка была отключена, отладка казалась проще. : D

Так что я создал мой случай функцию, чтобы преобразовать римские цифры:

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; 

$$ 

После этого я объявил вторую функцию, необходимую для преобразования. Я не знаю, можете ли вы объявить функцию внутри функции ... и я не хотел тратить больше времени на это. Вы можете объявить функцию внутри процедуры. Так или иначе. ПРЕДУПРЕЖДЕНИЕ. Эта функция не является доказательством BAD-цифр, таких как IIX. Цифры вроде этого или будут плохо подсчитаны. Также 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, а в другой структуре таблицы и сортировке.

+0

Это может быть «лучше»: 'SET currentintnum = 0 + convRomanNumeralSubFunction (SUBSTRING (число, счетчик, 1));' И добавьте 'DETERMINISTIC' перед' BEGIN'. –

+0

'convRomanNumeral ('MCMXLIV')' = 1944. Хорошо. –

+0

Прохладный, спасибо Рик. :) –

0

Лучший способ сделать это - добавить еще один столбец, который имеет сортируемый эквивалент этой строки. И используйте код, отличный от SQL, для разбора и построения этого столбца до, вставляемого в таблицу.

+0

Спасибо Рику за ответ на мой вопрос.Я должен сказать, что обычно я делаю это так, как вы писали, но это одноразовое исключение. Я думал, что никто не ответит мне, и я уже решил это самостоятельно (yay!). Я отправлю решение (что я делаю неправильно) для будущих пользователей. Кроме того, знаете ли вы, что не так с моим вопросом? Потому что кто-то дал мне минус за это. Это довольно сложно для новых пользователей, когда они получают минус для новых вопросов: p или, может быть, я не должен беспокоиться об этом. : D –

+0

Я часто не могу понять, почему кто-то опрокидывает вопрос. Я согласен, что это должно быть возможно в SQL; Я, вероятно, просмотрю его, когда вы опубликуете его. Насколько велика может быть римская цифра? Если это только I, II, III, IIII, вы можете использовать 'LENGTH()'. –

+0

Hi again @Rick, я добавил свое решение - хотите ли вы добавить что-то к нему из себя? –