Как извлечь значения из столбца и обновить результат в другом столбце - PullRequest
0 голосов
/ 30 августа 2018

у меня есть эта таблица:

CREATE TABLE MyTable (
    IdDate int,
    FullDate varchar(255)
);

insert into MyTable (IdDate,FullDate)
VALUES (0, 'Nº1 (26) - Friday 4, January 2014'),
       (0,'Nº2 (64) - Monday 10, February 2015')

Я хочу извлечь из FullDate что-то вроде этого:

1 2014 01 04
2 2015 02 10

1st number is extracted from Nº1
2nd number is extracted from Year
3rd number is extracted from Month (convert January to 01)
4th number is extracted from day (if day < 10, add 0 at the beginning: 01,02... )

И обновите новое значение, извлеченное в первом столбце с именем IdDate

Мой окончательный результат должен быть таким:

IdDate        FullDate
120140104     Nº1 (26) - Friday 4, January 2014
220150210     Nº2 (64) - Monday 10, February 2015

Ответы [ 4 ]

0 голосов
/ 30 августа 2018

Это извлечет значение даты. Он просто ищет запятую, резервирует несколько символов и захватывает дату, снимает запятую и рассматривает ее как военную дату.

select convert(date,  
   replace(substring(FullDate, charindex(',', FullDate) - 2, 100), ',', ''), 106)

Используйте format() или стиль даты 112, чтобы получить желаемый результат. Первый символ, по-видимому, просто substring(FullDate, 3, 1), поэтому просто добавьте его вперед.

0 голосов
/ 30 августа 2018

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

* ** 1003 тысяча два * Пример
Declare @YourTable table (IdDate int,FullDate varchar(max))
Insert Into @YourTable values
 (0,'Nº1 (26) - Friday 4, January 2014')
,(0,'Nº2 (64) - Monday 10, February 2015')

Update A
   set IdDate = substring(Pos1,3,10)
              + try_convert(varchar(10),try_convert(date,Pos6+' '+Pos5+' '+Pos7),112)
 From  @YourTable A
 Cross Apply [dbo].[tvf-Str-Parse-Row](FullDate,' ') B

Returns

IDDate      FullDate
120140104   Nº1 (26) - Friday 4, January 2014
220150210   Nº2 (64) - Monday 10, February 2015

Если это помогает с визуализацией, TVF возвращает

enter image description here

Функция при наличии интереса

CREATE FUNCTION [dbo].[tvf-Str-Parse-Row] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (
    Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
          ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
          ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
          ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
          ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
          ,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
          ,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(max)')))
          ,Pos8 = ltrim(rtrim(xDim.value('/x[8]','varchar(max)')))
          ,Pos9 = ltrim(rtrim(xDim.value('/x[9]','varchar(max)')))
    From  (Select Cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A 
)

или без функции

Update A
   set IdDate = substring(Pos1,3,10)
              + try_convert(varchar(10),try_convert(date,Pos6+' '+Pos5+' '+Pos7),112)
 From  @YourTable A
 Cross Apply (
                Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
                      ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
                      ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
                      ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
                      ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
                      ,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
                      ,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(max)')))
                From  (Select Cast('<x>' + replace((Select replace(FullDate,' ','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A 
             ) B

EDIT

Это расширенная версия решения Шона

Update @YourTable 
   set IdDate = substring(left(FullDate,charindex(' ',FullDate)-1),3,25)
               +try_convert(varchar(10),try_convert(date,replace(substring(FullDate, charindex(',', FullDate) - 2, 100), ',', '')),112)


Select * from @YourTable
0 голосов
/ 30 августа 2018

Если вам придется бороться с этим без использования функции, как написал Джон (что я и сделал бы), вы можете покопаться и начать кошмарный путь строковых функций. Проблема в том, что t-sql не очень хорош в манипулировании строками.

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

update MyTable
set IdDate = substring(FullDate, 3, CHARINDEX(' ', FullDate) - 3)
    + Right(FullDate, 4)
    + right('0' + convert(varchar(2), datepart(month, convert(date, replace(substring(substring(FullDate, charindex('-', FullDate) + 2, len(FullDate)), charindex(' ', substring(FullDate, charindex('-', FullDate) + 2, len(FullDate))) + 1, len(FullDate)), ',', '')))), 2)
    + right('0' + convert(varchar(2), datepart(day, convert(date, replace(substring(substring(FullDate, charindex('-', FullDate) + 2, len(FullDate)), charindex(' ', substring(FullDate, charindex('-', FullDate) + 2, len(FullDate))) + 1, len(FullDate)), ',', '')))), 2)

select * from MyTable

Тогда спросите человека, который решил хранить данные, как это, почему они это сделали? Это совсем не то, как обрабатывать данные.

0 голосов
/ 30 августа 2018
1st number is extracted from Nº1
2nd number is extracted from Year
3rd number is extracted from Month (convert January to 01)
4th number is extracted from day (if day < 10, add 0 at the beginning: 01,02... )

Используйте строковые функции SQL Server для выполнения следующих действий

  1. Получить символы между и первым пробелом, следующим за ним.
  2. Получить последние 4 символа
  3. Используйте выражение CASE, чтобы сгенерировать номер месяца на основе того, какое название месяца похоже на строку
  4. Получите 2 символа перед запятой и замените все пустые символы на них на 0.

И объединить эти 4 значения вместе.

...