2016-05-26 7 views
1

Я пытаюсь извлечь дату min из строки varchar.Извлечь Min Date из строки с несколькими датами с использованием SQL Server

Данные в поле выглядит следующим образом

QTY DIFFERENCE - PO LINE 6. 147 ON PO/192 ON INVOICE 

5/18/2016 4:18:52 PM by ROOFING\ebuchanan 
ANDREW SANTORI ISSUED THIS PO, PLEASE SEND TO HIS QUE 

5/21/2016 9:48:42 AM by ROOFING\knaylor 
RE-ROUTED TO ATS 

Используя этот код

SELECT 
    UISeq, 
    LEFT(SUBSTRING(Notes, PATINDEX('%[0-9/]%', Notes), 8000), 
     PATINDEX('%[^0-9/]%', SUBSTRING(Notes, PATINDEX('%[0-9/]%', Notes), 8000) + 'X') -1) as 'MaxDate' 
FROM 
    bAPUI 
WHERE 
    Notes IS NOT NULL 
ORDER BY 
    UISeq 

Я получаю этот результат из записи выше

6 

Я также получаю

01/01/2000 

В других полях

Как исправить код, чтобы возвращать только минимальную дату в каждом поле записи?

UISeq MinDate 
    2  3 
    3  5 
13 4/1/2016 
15  1 
17 
18 4/15/2016 
19  3 
20 4/15/2016 
40 05/22/16 
43 05/22/16 
54 5/18/16 

пост Джона вне моей текущей способности

Я создал функцию, вот код для извлечения данных

Declare @Str varchar(max); 

Select @Str as Notes, Min(Key_Value) 

from bAPUI, [dbo].[SA-udf-Str-Parse](replace(@Str,char(13),' '),' ') 

Where Key_Value like '%/%' 
    and len(Key_Value)>=10 

То, что я не понимая в том, как получить bAPUI .Написать таблицу/поле в оператор select.

+1

Удачи. Этот тип разбора на данные, которые, как представляется, являются свободным текстом, невозможно. Здесь нет ничего конкретного, чтобы вы могли определить, где начинается дата или где она заканчивается.Вероятно, вы могли бы выделить даты, но было бы сложно продлить это, чтобы включить временную часть. –

+0

Является ли образец вы отправили содержимое одной строки? Или это несколько строк? Предоставление некоторого понимания вашей таблицы даст вам много хорошего здесь. –

+0

Шон: Я не беспокоюсь о времени, просто о дате. Спасибо – Steve

ответ

1

Следующая строка использует парсер UDF. Возможно, в ваших данных или даже в этом примере были chr (13), поэтому мне пришлось выполнить replace(), могут быть другие расширенные символы, которые могут быть захвачены.

Declare @Str varchar(max) 
Set @Str='QTY DIFFERENCE - PO LINE 6. 147 ON PO/192 ON INVOICE 

5/18/2016 4:18:52 PM by ROOFING\ebuchanan 
ANDREW SANTORI ISSUED THIS PO, PLEASE SEND TO HIS QUE 

5/21/2016 9:48:42 AM by ROOFING\knaylor 
RE-ROUTED TO ATS' 

Select * from [dbo].[udf-Str-Parse](replace(@Str,char(13),' '),' ') 
Where Key_Value like '%/%' 
    and len(Key_Value)>=10 

Возвращает

Key_PS Key_Value 
13  5/18/2016 
28  5/21/2016 

Хотя с быстрым изменением

Select Min(Key_Value) from [dbo].[udf-Str-Parse](replace(@Str,char(13),' '),' ') 
Where Key_Value like '%/%' 
    and len(Key_Value)>=10 

Возвращает

5/18/2016 

Есть миллионы вариаций, но здесь моя.

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@delimeter varchar(10)) 
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--  Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
--  Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|') 

Returns @ReturnTable Table (Key_PS int IDENTITY(1,1) NOT NULL , Key_Value varchar(500)) 

As 

Begin 
    Declare @intPos int,@SubStr varchar(500) 
    Set @IntPos = CharIndex(@delimeter, @String) 
    Set @String = Replace(@String,@[email protected],@delimeter) 
    While @IntPos > 0 
     Begin 
     Set @SubStr = Substring(@String, 0, @IntPos) 
     Insert into @ReturnTable (Key_Value) values (@SubStr) 
     Set @String = Replace(@String, @SubStr + @delimeter, '') 
     Set @IntPos = CharIndex(@delimeter, @String) 
     End 
    Insert into @ReturnTable (Key_Value) values (@String) 
    Return 
End 

Таким образом, чтобы применить к данным

Select UISeq, 
     ,MinDate=(Select Min(Key_Value) from [dbo].[udf-Str-Parse](replace(Notes,char(13),' '),' ') Where Key_Value like '%/%' and len(Key_Value)>=10) 
FROM bAPUI 
WHERE Notes IS NOT NULL 
ORDER BYUISeq 

Я понятия не имею, как это будет работать на большом наборе данных

+0

Если вы не предоставите свой разделитель строк, это не полный ответ. –

+0

Я очень рекомендую вам заглянуть в замену этого. Использование цикла для этого очень медленно. Вот несколько лучших вариантов. http://sqlperformance.com/2012/07/t-sql-queries/split-strings Независимо от того, что вы получаете +1 от меня. –

+0

Поймет взгляд. Спасибо за ссылку. –

0

Super quick draft - используйте CHARINDEX И LEFT для извлечения всех символов до первого места, затем преобразуйте этот текст в DATE, затем используйте MIN для выбора даты EARLIEST.

enter image description here

select @str as string ,left(@str,CHARINDEX(' ',@str)) -- Get the position of the first space, then select all characters up to the space ,MIN(convert(date,left(@str,CHARINDEX(' ',@str)))) -- Convert the selected characters to a date and then use MIN to select earliest date

+0

Мой ответ может быть совершенно неправильным, если дата может быть ANYWHERE в строке - я думал, что строка начала с даты – Aron

+0

получила эту ошибку "Msg 241, уровень 16, состояние 1, строка 11 Конверсия не удалась при преобразовании даты и/или время от символьной строки " – Steve