Как вставить символ в строку каждые 3 символа справа - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть строка, состоящая из чисел. Длина строки варьируется от 1 до 9 символов. Я хочу вставить да sh (-) каждые три символа справа. Это будет актуально только для строк длиной не более трех символов. Это будет просто оператор выбора, так как я не хочу на самом деле обновлять саму строку.

Например,

8 should return 8
476 should return 476
4767 should return 4-767
45907392 should return 45-907-392
845907392 should return 845-907-392

Ответы [ 6 ]

1 голос
/ 20 апреля 2020

Начиная с SQL Server 2012, вы можете использовать функцию FORMAT, как описано в других ответах. Если вы хотите отформатировать строковое значение, например, 'abcde', вы можете использовать только строковые функции, подобные этой:

DECLARE @str VARCHAR(100) = '845907392';

-- 845-907-392
SELECT REVERSE(SUBSTRING(REVERSE(@str), 7, 3)) 
  + CASE WHEN LEN(@str)>6 THEN '-' ELSE '' END 
  + REVERSE(SUBSTRING(REVERSE(@str), 4, 3)) 
  + CASE WHEN LEN(@str)>3 THEN '-' ELSE '' END 
  + REVERSE(SUBSTRING(REVERSE(@str), 1, 3))

Вы также можете создать функцию:

CREATE FUNCTION dbo.GetFormatTripleDash (@str varchar(255))
RETURNS VARCHAR(255)
AS
BEGIN
  DECLARE @retStr VARCHAR(255) = REVERSE(SUBSTRING(REVERSE(@str), 7, 3)) 
    + CASE WHEN LEN(@str)>6 THEN '-' ELSE '' END 
    + REVERSE(SUBSTRING(REVERSE(@str), 4, 3)) 
    + CASE WHEN LEN(@str)>3 THEN '-' ELSE '' END 
    + REVERSE(SUBSTRING(REVERSE(@str), 1, 3))
  RETURN(@retStr)
END

Вы можете используйте эту функцию следующим образом:

-- 845-907-392
SELECT dbo.GetFormatTripleDash('845907392')

Более гибкое решение с использованием функции. Теперь вы можете использовать намного более длинное строковое значение и определить размер детали, разделенный символом -.

CREATE FUNCTION dbo.GetFormatDash (@str varchar(255), @partSize INT = 3)
RETURNS VARCHAR(255)
AS
BEGIN
  DECLARE @startSize INT = 0;
  DECLARE @retStr VARCHAR(255) = '';

  WHILE @startSize < LEN(@str)
  BEGIN
    SET @retStr = REVERSE(SUBSTRING(REVERSE(@str), @startSize + 1, @partSize)) + CASE WHEN @startSize > 0 THEN '-' ELSE '' END + @retStr;
    SET @startSize = @startSize + @partSize;
  END

  RETURN(@retStr)
END 

Вы можете использовать эту улучшенную функцию следующим образом:

-- 12-345-678-901-234-567-890
SELECT dbo.GetFormatDash('12345678901234567890', DEFAULT)
SELECT dbo.GetFormatDash('12345678901234567890', 3)

-- 12345-67890-12345-67890
SELECT dbo.GetFormatDash('12345678901234567890', 5)

демо на dbfiddle.uk

1 голос
/ 20 апреля 2020

Это должно работать:

select 
  *,
  replace(format(n,'#,#'),',','-')
from (values (8),(476),(4767),(45907392),(845907392)) x (n)

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

0 голосов
/ 20 апреля 2020

Решение с рекурсивным CTE:

with cte as (
  select col, len(col) - 3 pos from tablename
  union all 
  select 
    cast(left(col, pos) + '-' + right(col, len(col) - pos) as varchar(100)), 
    pos - 3
  from cte
  where pos > 0
)
select col from cte
where pos <= 0

См. Демоверсию . Результаты:

> | col         |
> | :---------- |
> | 8           |
> | 476         |
> | 845-907-392 |
> | 45-907-392  |
> | 4-767       |
0 голосов
/ 20 апреля 2020

Попробуйте это. Я уверен, что это также может быть расширено, чтобы учесть любое количество символов с небольшим усилием

declare @input nvarchar(100) = '845907392'
declare @separator char(1) = '-'

--option1 - CTE

;with dash1 as (
    select isnull(stuff(reverse(@input), 1+3, 0, @separator), reverse(@input)) as v
)
, dash2 as(
    select isnull(stuff(v, 1+7, 0, @separator), v) as v from dash1
)
select reverse(v) from dash2


--option2 - Non CTE
select reverse(isnull(stuff(isnull(stuff(reverse(@input), 1+3, 0, @separator), reverse(@input)), 1+7, 0, @separator), isnull(stuff(reverse(@input), 1+3, 0, @separator), reverse(@input))))
0 голосов
/ 20 апреля 2020

Это немного брутто, но это работает! Попробуйте, и дайте мне знать, если вы согласны

    SELECT
        CASE    
            WHEN LEN(yourColumn)>6 THEN format(CAST(YourColumn AS NUMERIC), '###-###-###') 
            WHEN LEN(YourColumn)>3 THEN format(CAST(YourColumn AS NUMERIC), '###-###')
            ELSE YourColumn
        END

Вот еще один способ сделать это, хотя больше печатать

    SELECT
        CASE    
            WHEN LEN(yourColumn)>6 THEN SUBSTRING(YourColumn, 1, 3) +'-'+ SUBSTRING(YourColumn, 4, 3)
            WHEN LEN(YourColumn)>3 THEN REVERSE(SUBSTRING(REVERSE(YourColumn), 1, 3) +'-'+ SUBSTRING(REVERSE(YourColumn), 4, 3))
            ELSE YourColumn
        END         
0 голосов
/ 20 апреля 2020

Попробуйте использовать функцию format().

Select Replace(format(8, '#,##0'), ',', '-')
Select Replace(format(476, '#,##0'), ',', '-')
Select Replace(format(45907392, '#,##0'), ',', '-')
Select Replace(format(845907392, '#,##0'), ',', '-')

Live db <> fiddle demo.

enter image description here

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