Как разбить каждую цифру числа на разные строки - PullRequest
0 голосов
/ 27 мая 2019

Я хочу, чтобы что-то вроде SELECT splitDigits(123456789) as digits вернулось:

 digits 
-------
  1
  2
  3
  4
  5
  6
  7
  8
  9

Что мне действительно нужно

Я пытаюсь сделать эту проверку (идентификатор RUC Перу) в хранимой процедуре:

Я пытаюсь избегать циклов, поэтому я застрял на первом шаге, который состоит в том, чтобы захватить первые 10 цифр и умножить каждую цифру на фиксированный скаляр, который зависит от позиции, затем я должен сложить все эти умножения .

Это в основном векторное умножение, и я пытаюсь построить вектор из первых 10 цифр 11-значного числа.

Ответы [ 4 ]

2 голосов
/ 27 мая 2019

Так как формат числа фиксирован, вам просто нужна базовая математика:

SELECT num div          10 % 10 * 2
     + num div         100 % 10 * 3
     + num div        1000 % 10 * 4
     + num div       10000 % 10 * 5
     + num div      100000 % 10 * 6
     + num div     1000000 % 10 * 7
     + num div    10000000 % 10 * 2
     + num div   100000000 % 10 * 3
     + num div  1000000000 % 10 * 4
     + num div 10000000000 % 10 * 5 AS s
FROM (
    SELECT 20503644968 AS num
) AS t
-- 157
1 голос
/ 27 мая 2019

Тогда я должен сложить все умножения. После этого есть некоторые тривиальные вычисления с результатом суммы, применяя некоторый модуль и дополняет, но это выходит за рамки этого вопроса.

Почему выходит за рамки этого вопроса, так как мы любим решать эти вещи.

Запрос

SELECT 
 11 - (SUM(vector_input.vector_input__summed) % 11)
FROM (

SELECT 
 vector.item * input.item AS vector_input__summed

FROM (
 SELECT 
  DISTINCT
    SUBSTRING(5432765432, vector_number_generator.number, 1) AS item
    ,  vector_number_generator.number  AS position
FROM (
  SELECT 
   @vector_row := @vector_row + 1 AS number
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION   SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) AS row_1
  CROSS JOIN (
    SELECT @vector_row := 0 
  ) AS init_user_params 
) AS vector_number_generator

) AS vector
INNER JOIN (
  SELECT 
  DISTINCT
       SUBSTRING(2050364496, number_generator.number, 1) AS item
    ,  number_generator.number  AS position
FROM (
  SELECT 
   @row := @row + 1 AS number
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION   SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row1
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION  SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row2
  CROSS JOIN (
    SELECT @row := 0 
  ) AS init_user_params 
) AS number_generator
) AS input
ON
 vector.position = input.position
) AS vector_input

Результат

| 11 - (SUM(vector_input.vector_input__summed) % 11) |
| -------------------------------------------------- |
| 8                                                  |

См. демо

Если также следует использовать модуль 10, который, как я полагаю, должен быть
((11 - (SUM(vector_input.vector_input__summed) % 11)) % 10) см. демо

1 голос
/ 27 мая 2019
SELECT
    SUBSTR(3987654321, idx, 1) AS SplitDigits,
    3 * (SUBSTR(3987654321, idx, 1)) AS ConstTimesSplitDigits
   -- SUM(SUBSTR(2050364496, idx, 1) * (SUBSTR(5432765432, idx, 1))) AS Result
FROM (SELECT @cnt := 0) A
-- cross join any table has rows greater than or equal to your liking
CROSS JOIN (SELECT (@cnt := @cnt + 1) idx FROM INFORMATION_SCHEMA.TABLES LIMIT 10) B
;
0 голосов
/ 28 мая 2019

Использование ответов Наэ и ответов Рэймонда

Чтобы разделить число фиксированной длины на отдельные строки

SELECT
   SUBSTR(1234567890123, range10, 1)
FROM (
  SELECT 1 range10
  UNION SELECT 2
  UNION SELECT 3
  UNION SELECT 4
  UNION SELECT 5
  UNION SELECT 6
  UNION SELECT 7
  UNION SELECT 8
  UNION SELECT 9
  UNION SELECT 10
  UNION SELECT 11
  UNION SELECT 12
  UNION SELECT 13
) A

Количество символов переменной длины см. Наэ ответ


Вся проверка RUC превращена в функцию

CREATE FUNCTION `validate_ruc`(`ruc` BIGINT) RETURNS binary(1)
BEGIN
DECLARE isValid BINARY;

IF LENGTH(ruc) != 11 THEN RETURN FALSE; END IF;

SELECT
  ((11 - (sum % 11)) % 10) = (ruc % 10)
INTO isValid
FROM (
  SELECT
     SUM( SUBSTR(ruc, range10, 1) * (SUBSTR(5432765432, range10, 1)) ) AS sum
  FROM (
    SELECT 1 range10
    UNION SELECT 2
    UNION SELECT 3
    UNION SELECT 4
    UNION SELECT 5
    UNION SELECT 6
    UNION SELECT 7
    UNION SELECT 8
    UNION SELECT 9
    UNION SELECT 10
  ) A
) B;

RETURN isValid;

END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...