Преобразует неотрицательные числа в диапазоне BIGINT в английские слова.
CREATE FUNCTION dbo.tvfNumberToEnglishWords (@Number BIGINT) -- BIGINT is 64 bit signed integer
-- Converts whole numbers into English words. Returns an empty string for negative numbers.
-- Parameter @Number is a 64-bit signed integer, which allows a range of zero to 9,223,372,036,854,775,807
-- 2018-08-29 - Dave Boltman - Created
RETURNS TABLE AS
RETURN
WITH
Smalls AS (
SELECT n, Name
FROM (VALUES (1, 'one'), (2, 'two'), (3, 'three'), (4, 'four'), (5, 'five'), (6, 'six'), (7, 'seven'),
(8, 'eight'), (9, 'nine'), (10, 'ten'), (11, 'eleven'), (12, 'twelve'), (13, 'thirteen'), (14, 'fourteen'),
(15, 'fifteen'), (16, 'sixteen'), (17, 'seventeen'), (18, 'eighteen'), (19, 'nineteen')) AS s (n, Name)
),
Decades AS (
SELECT n, Name
FROM (VALUES (2, 'twenty'), (3, 'thirty'), (4, 'forty'), (5, 'fifty'),
(6, 'sixty'), (7, 'seventy'), (8, 'eighty'), (9, 'ninety')) AS t (n, Name)
),
Groups AS (
SELECT n, Name
FROM (VALUES (0, ''), (1, ' thousand'), (2, ' million'), (3, ' billion'), (4, ' trillion'), (5, ' quadrillion'), (6, ' quintillion')
-- up to here is enough for 64 bit integers
) AS g (n, Name)
),
cte AS (
-- Level 0 : Anchor query to start the processing
SELECT
CAST (0 AS INT) AS Level,
CAST (@Number % 1000 AS BIGINT) Lowest3Digits,
cast (@Number / 1000 AS BIGINT) AS RemainingDigits,
CASE WHEN @Number = 0 THEN CAST ('zero' AS VARCHAR(1024)) ELSE '' END TextSoFar
UNION ALL
-- Recursive query based on the previous level
SELECT
Level + 1 AS Level, -- increase the level
RemainingDigits % 1000 AS Lowest3Digits,
RemainingDigits / 1000 AS RemainingDigits,
-- Busniess part is here
CAST (
CASE WHEN (RemainingDigits > 0) AND (Lowest3Digits > 0)
THEN CASE WHEN (Hundreds > 0) OR (Level > 0) THEN ', ' ELSE ' and ' END -- change ' and ' to ' ' for American English
ELSE ''
END
+ CASE WHEN Hundreds > 0 THEN (SELECT Name FROM Smalls WHERE n = Hundreds) + ' hundred' ELSE '' END
+ CASE WHEN (Hundreds > 0) AND (TensUnits > 0) THEN ' and ' ELSE '' END
+ CASE WHEN TensUnits >= 20
THEN (SELECT Name FROM Decades WHERE n = Tens)
+ CASE WHEN Units > 0 THEN (SELECT '-' + Name FROM Smalls WHERE n = Units) ELSE '' END
ELSE CASE WHEN TensUnits > 0 THEN (SELECT Name FROM Smalls WHERE n = TensUnits) ELSE '' END
END
+ CASE WHEN Lowest3Digits > 0 THEN (SELECT Name FROM Groups WHERE n = Level) ELSE '' END
+ TextSoFar
AS VARCHAR(1024)) AS TextSoFar
FROM
( SELECT Level, Lowest3Digits, RemainingDigits, TextSoFar,
Lowest3Digits / 100 AS Hundreds, Lowest3Digits % 100 AS TensUnits, (Lowest3Digits % 100) / 10 AS Tens, Lowest3Digits % 10 AS Units
FROM cte -- Dave Boltman made this code
) AS l
WHERE -- condition for exiting the recursion
(Lowest3Digits > 0) OR (RemainingDigits > 0)
)
SELECT TOP 1 TextSoFar AS EnglishText FROM cte ORDER BY Level DESC
GO
Ограниченные данные испытаний
SELECT n, dbo.fnNumberToEnglishWords(n) AS AsText
FROM (VALUES (0),(-1),(1),(19),(63),(100),(101),(147),(1000),(1001),(1056),(1100),(1110),(900456),(76543),(1000000),(1000001),(1001001),(1001000),(1234567),(1234567890),(9223372036854775807)) x (n)
Результаты
n AsText
--------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0 zero
-1
1 one
19 nineteen
63 sixty-three
100 one hundred
101 one hundred and one
147 one hundred and forty-seven
1000 one thousand
1001 one thousand and one
1056 one thousand and fifty-six
1100 one thousand, one hundred
1110 one thousand, one hundred and ten
900456 nine hundred thousand, four hundred and fifty-six
76543 seventy-six thousand, five hundred and forty-three
1000000 one million
1000001 one million and one
1001001 one million, one thousand and one
1001000 one million, one thousand
1234567 one million, two hundred and thirty-four thousand, five hundred and sixty-seven
1234567890 one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety
9223372036854775807 nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and seven
Редактировать: (перенесено сюда) Используется текущий британский английский. Если вы предпочитаете американский английский, просто измените один из строковых литералов выше с ' and '
на ' '
(в коде есть комментарий, который описывает, как). Под текущим британским английским я подразумеваю короткую шкалу , которая всегда использовалась в американском английском (т. Е. «Миллиард» означает 1 000 000 000), а не более старую длинную шкалу (используется в британском английском). примерно до 70-х годов, где «миллиард» означает миллион миллионов, или 1 000 000 000 000).
Я включил запятые в результат, хотя я не уверен, что это стандарт. Просто удалите запятую в строковом литерале, если вы этого не хотите.