один столбец разделить на более столбец SQL Server 2008? - PullRequest
2 голосов
/ 12 мая 2011

Название таблицы: Table1

id   name 
1    1-aaa-14 milan road
2    23-abcde-lsd road
3    2-mnbvcx-welcoome street

Я хочу получить такой результат:

Id   name   name1    name2  
1    1      aaa      14 milan road
2    23     abcde    lsd road
3    2      mnbvcx   welcoome street

Ответы [ 4 ]

3 голосов
/ 12 мая 2011

Эта функция должна дать вам то, что вам нужно.

--Drop Function Dbo.Part
Create Function Dbo.Part
    (@Value Varchar(8000)
    ,@Part Int
    ,@Sep Char(1)='-'
)Returns Varchar(8000)
As Begin
Declare @Start Int
Declare @Finish Int
Set @Start=1
Set @Finish=CharIndex(@Sep,@Value,@Start)
While (@Part>1 And @Finish>0)Begin
    Set @Start=@Finish+1
    Set @Finish=CharIndex(@Sep,@Value,@Start)
    Set @Part=@Part-1
End
If @Part>1 Set @Start=Len(@Value)+1 -- Not found
If @Finish=0 Set @Finish=Len(@Value)+1 -- Last token on line
Return SubString(@Value,@Start,@Finish-@Start)
End

Использование:

Select ID
      ,Dbo.Part(Name,1,Default)As Name
      ,Dbo.Part(Name,2,Default)As Name1
      ,Dbo.Part(Name,3,Default)As Name2
  From Dbo.Table1

Это довольно трудоемкий процесс, поэтому если Table1 очень длинный, вам следует записывать результаты в другую таблицу, которую вы можете обновлять время от времени (возможно, один раз в день, ночью).

Еще лучше, вы можете создать триггер, который автоматически обновляет Таблицу 2 при каждом изменении Таблицы1. Предполагая, что идентификатор столбца является первичным ключом:

Create Table Dbo.Table2(
    ID Int Constraint PK_Table2 Primary Key,
    Name Varchar(8000),
    Name1 Varchar(8000),
    Name2 Varchar(8000))
Create Trigger Trigger_Table1 on Dbo.Table1 After Insert,Update,Delete
As Begin
If (Select Count(*)From Deleted)>0
    Delete From Dbo.Table2 Where ID=(Select ID From Deleted)
If (Select Count(*)From Inserted)>0
    Insert Dbo.Table2(ID, Name, Name1, Name2)
    Select ID
          ,Dbo.Part(Name,1,Default)
          ,Dbo.Part(Name,2,Default)
          ,Dbo.Part(Name,3,Default)
      From Inserted
End

Теперь сделайте ваши манипуляции с данными (Вставка, Обновление, Удалить) в Таблице 1, но вместо этого сделайте ваши операторы Выбрать в Таблице 2.

1 голос
/ 13 мая 2011
select T.id,
    substring(T.Name, 1, D1.Pos-1) as Name,
    substring(T.Name, D1.Pos+1, D2.Pos-D1.Pos-1) as Name1,
    substring(T.Name, D2.Pos+1, len(T.name)) as Name2
from Table1 as T
  cross apply (select charindex('-', T.Name, 1)) as D1(Pos)
  cross apply (select charindex('-', T.Name, D1.Pos+1)) as D2(Pos)

Тестирование производительности предлагаемых решений

Настройка:

create table Table1
(
  id int identity primary key,
  Name varchar(50)
)
go

insert into Table1
select '1-aaa-14 milan road' union all
select '23-abcde-lsd road' union all
select '2-mnbvcx-welcoome street'

go 10000

Результат:

enter image description here

1 голос
/ 13 мая 2011

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

WITH Table1 (id, name) AS (
  SELECT 1, '1-aaa-14 milan road' UNION ALL
  SELECT 2, '23-abcde-lsd road' UNION ALL
  SELECT 3, '2-mnbvcx-welcoome street'
),
cutpositions AS (
  SELECT
    id, name,
    rownum = 1,
    startpos = 1,  
    nextdash = CHARINDEX('-', name + '-')
  FROM Table1
  UNION ALL
  SELECT
    id, name,
    rownum + 1,
    nextdash + 1,
    CHARINDEX('-', name + '-', nextdash + 1)
  FROM cutpositions c
  WHERE nextdash < LEN(name)
)
SELECT
  id,
  [1] AS name,
  [2] AS name1,
  [3] AS name2
  /* add more columns here */
FROM (
  SELECT
    id, rownum,
    part = SUBSTRING(name, startpos, nextdash - startpos)
  FROM cutpositions
) s
PIVOT ( MAX(part) FOR rownum IN ([1], [2], [3] /* extend the list here */) ) x

Без дополнительных модификаций этот запрос может разделять имена, состоящие из 100 частей (это максимальная глубина рекурсии по умолчанию, которую можно изменить), но может только отображать не более 3 из них. Вы можете легко расширить его на любое количество частей, которые вы хотите отобразить, просто следуйте инструкциям в комментариях.

0 голосов
/ 12 мая 2011

если у вас всегда будет 2 черты, вы можете сделать следующее, используя PARSENAME

--testing table
CREATE TABLE #test(id INT, NAME VARCHAR(1000))


INSERT #test VALUES(1, '1-aaa-14 milan road')
INSERT #test VALUES(2, '23-abcde-lsd road')
INSERT #test VALUES(3, '2-mnbvcx-welcoome street')

SELECT id,PARSENAME(name,3) AS name,
PARSENAME(name,2) AS name1,
PARSENAME(name,1)AS name2
 FROM (
SELECT id,REPLACE(NAME,'-','.') NAME
FROM #test)x

, если у вас есть точки в столбце имени, вы должны сначала заменить их, а затем заменить их обратно наточки в конце

, например, с использованием тильды для замены точки

 INSERT #test VALUES(3, '5-mnbvcx-welcoome street.')


SELECT id,REPLACE(PARSENAME(name,3),'~','.') AS name,
REPLACE(PARSENAME(name,2),'~','.')  AS name1,
REPLACE(PARSENAME(name,1),'~','.') AS name2
 FROM (
SELECT id,REPLACE(REPLACE(NAME,'.','~'),'-','.') NAME
FROM #test)x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...