MSSQL - разделить поле на 3 поля - PullRequest
3 голосов
/ 10 марта 2009

У меня есть набор результатов, состоящий из 1 столбца, и в этом случае 2 строки, один столбец [ProductDescription] - это поле varchar, которое содержит 3 фрагмента информации (я не разработал его). в 3 дополнительных поля, используя запрос

до

/------------------------------\
|ProductDescription            |
|------------------------------|
|DB1 - DB2 - DB3               |
|DataBit1 - DataBit2 - DataBit3|
\------------------------------/

После

/---------------------------------------------------------\
|Field1  |Field2  |Field3  |ProductDescription            |  
|---------------------------------------------------------|  
|DB1     |DB2     |DB3     |DB1 - DB2 - DB3               |  
|DataBit1|DataBit2|DataBit3|DataBit1 - DataBit2 - DataBit3|  
\---------------------------------------------------------/

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

Ответы [ 6 ]

4 голосов
/ 10 марта 2009

Это не красиво, но работает и дает вам то, что вы ищете, для вашего конкретного случая ... Если в вашем ProductDescription есть переменное число токенов, вам, вероятно, потребуется создать сохраненный proc для управления вашим состоянием при разборе строки, поскольку это быстро станет неуправляемым.

create table #table(productdescription varchar(255))
go
/* Demonstrate it working in a 'pretty' case */
INSERT INTO #TABLE (ProductDescription) values ('abc - def - ghi')
go

/* Demonstrate it working in a 'ugly' case */
insert into #table (ProductDescription) values ('jklsaf -mnoa-psdfaqr')
go

SELECT RTRIM(LTRIM(SUBSTRING(ProductDescription, 0, CHARINDEX('-', ProductDescription)-1))) as Field1,

RTRIM(LTRIM(SUBSTRING(ProductDescription, CHARINDEX('-', ProductDescription)+1, (CHARINDEX('-', ProductDescription, CHARINDEX('-', ProductDescription)+1)) - (CHARINDEX('-', ProductDescription)+1)))) as Field2,

RTRIM(LTRIM(SUBSTRING(ProductDescription, CHARINDEX('-', ProductDescription, CHARINDEX('-', ProductDescription)+1)+1, LEN(ProductDescription)))) as Field3
FROM #table
go

Надеюсь, это поможет!

3 голосов
/ 10 марта 2009

Если в столбце ProductDescription всегда есть три элемента информации и что разделитель всегда равен "-", то следующие действия должны помочь:

SELECT
    SUBSTRING(ProductDescription, 1,
        CHARINDEX(' - ', ProductDescription) - 1
    ) AS Field1,
    SUBSTRING(ProductDescription,
        CHARINDEX(' - ', ProductDescription) + 3,
        CHARINDEX(' - ', ProductDescription,
            CHARINDEX(' - ', ProductDescription) + 3
        ) - (CHARINDEX(' - ', ProductDescription) + 3)
    ) AS Field2,
    SUBSTRING(ProductDescription,
        CHARINDEX(' - ', ProductDescription,
            CHARINDEX(' - ', ProductDescription) + 3) + 3,
        LEN(ProductDescription)
    ) AS Field3,
    ProductDescription
FROM your_table
2 голосов
/ 10 марта 2009

Как насчет встроенной функции, которая принимает строку, разделитель и какую часть вы хотите вернуть

 Create Function dbo.GetPart(@InString as varchar(1000)
     , @Part as int
     , @Delim as varchar(10))
    Returns varchar(1000) as 
    Begin
        Declare @CurrentPart int
        Declare @i int 
        Declare @j int
        Declare @Ret varchar(1000)
        Set @Ret = ''
        Set @i = 0
        Set @InString = Replace(@InString, ' ', '')

        Set @CurrentPart = 1
        while (@CurrentPart <= @Part)
        Begin
            Set @j =  charindex(@Delim, @InString, @i + 1 ) 
            if @j = 0 set @j = len(@InString) + 1
            if ((@j - @i) > 0 and @CurrentPart = @Part)
            Begin   
                Set @Ret =  Substring(@InString, @i , @j - @i) 
                If @Ret = '' set @ret = 'Weird'
                break
            End
            Set @i = charindex(@Delim, @InString, @i) + len(@delim)
            Set @CurrentPart = @CurrentPart + 1
        End
        if @Ret = '' Set @Ret = 'inconveivable'
        Return @Ret
    End
    GO 
    Select dbo.GetPart('DB1 - DB2 - DB3',1, '-') as Field1
    ,dbo.GetPart('DB1 - DB2 - DB3',2, '-') as Field2
    , dbo.GetPart('DB1 - DB2 - DB3',3, '-') as Field3

    Select dbo.GetPart('DataBit1 - DataBit2 - DataBit3',1, '-') as Field1
    ,dbo.GetPart('DataBit1 - DataBit2 - DataBit3',2, '-') as Field2
    , dbo.GetPart('DataBit1 - DataBit2 - DataBit3',3, '-') as Field3
0 голосов
/ 20 апреля 2012

Лично я бы проверил на «-» и использовал бы это как мой разделитель вместо просто «-» по той простой причине, что многие записи могут быть расставлены через дефис. Замените трехсимвольную комбинацию запятой и, по сути, сгенерируйте CSV (этап 1) и проанализируйте строки CSV в таблице.

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

Mac

0 голосов
/ 14 апреля 2009

Вот еще одно решение. Предполагается, что в описании продукта нет точки (.):

SELECT 
    LTRIM(PARSENAME(REPLACE(ProductDescription,'-','.'),3)) DB1, 
    LTRIM(PARSENAME(REPLACE(ProductDescription,'-','.'),2)) DB2, 
    LTRIM(PARSENAME(REPLACE(ProductDescription,'-','.'),1)) DB3, 
    ProductDescription
FROM #TABLE T
0 голосов
/ 10 марта 2009

Спасибо, Люк, это близко, но не точно.

/----------------------------------------------------------------------------\
|DB1        |DB2       |DB3            |ProductDescription                   |
|----------------------------------------------------------------------------|
|Loading    |Trailer   |Albert Moving  |Loading - Trailer - Albert Moving    |
|Unloading  |Trailer - |Moving Staffers|Unloading - Trailer - Moving Staffers|
\----------------------------------------------------------------------------/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...