Добавьте нули для чисел, используя CTE в Sql Server 2005 - PullRequest
0 голосов
/ 16 июня 2011

У меня есть некоторые данные, как показано ниже

ID Data
1   a
1   2
1   b
1   1
2   d
2   3
2   r

Требуемый вывод

ID    Data
1     a
1     NULL
1     NULL
1     b
1     NULL
2     d
2     NULL
2     NULL
2     NULL
2     r

Что такое выход, для чисел он заменяется многими значениями NULL.Например, для числового значения 2 это будет 2 пустых значения.

Значение ddl соответствует

Declare @t table(ID int, data varchar(10))

Insert into @t
Select 1, 'a' union all select 1, '2' union all select 1, 'b' union all select 1, '1'  union all select 2,'d' union all
select 2,'3' union all select 2, 'r'

select * from @t

Пожалуйста, дайте решение на основе CTE.У меня уже есть процедурный подход, но мне нужно иметь представление о решении на основе CTE.

Решение, которое я использую в настоящее время

CREATE FUNCTION [dbo].[SPLIT] (
 @str_in VARCHAR(8000)
)
RETURNS @strtable TABLE (id int identity(1,1), strval VARCHAR(8000))

AS

BEGIN

DECLARE @tmpStr VARCHAR(8000), @tmpChr VARCHAR(5), @ind INT = 1, @nullcnt INT = 0
SELECT @tmpStr = @str_in

WHILE LEN(@tmpStr) >= @ind
BEGIN

 SET @tmpChr = SUBSTRING(@tmpStr,@ind,1)
 IF ISNUMERIC(@tmpChr) = 0
  INSERT INTO @strtable SELECT @tmpChr
 ELSE
  WHILE @nullcnt < @tmpChr
  BEGIN
   INSERT INTO @strtable SELECT NULL
   SET @nullcnt = @nullcnt + 1
  END
 SELECT @ind = @ind + 1, @nullcnt = 0

END

RETURN

END
GO

Вызов

SELECT * from dbo.SPLIT('abc2e3g')

Я не хочу делать это, используя функцию, но решение CTE.

Причина: Я изучаю CTE и пытаюсь решить проблемы, используя его.Пытаться выйти из процедурного / рБар подхода.

Спасибо

Ответы [ 2 ]

0 голосов
/ 16 июня 2011

Установка:

declare @t table(UniqueID int identity(1,1), ID int, data varchar(10))

insert into @t
select 1, 'a' union all 
select 1, '2' union all
select 1, 'b' union all
select 1, '1' union all
select 2, 'd' union all
select 2, '3' union all
select 2, 'r'

Запрос:

;with cte
as
(
    select UniqueId, id, data, case when isnumeric(data) = 1 then cast(data as int) end Level
    from @t
    union all
    select UniqueId, id, null, Level - 1
    from cte
    where Level > 0
)
select id, data
from cte
where Level is null or data is null
order by UniqueID, Level

Выход:

id          data
----------- ----------
1           a
1           NULL
1           NULL
1           b
1           NULL
2           d
2           NULL
2           NULL
2           NULL
2           r

Я добавил UniqueId, так как должно быть какое-то поле, определяющее порядок в исходной таблице.

0 голосов
/ 16 июня 2011

Если у вас есть таблица чисел, это становится довольно просто.

;WITH Nbrs ( Number ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + Number FROM Nbrs WHERE Number < 8000 )
SELECT
   M.UniqueID, M.ID, Data
FROM
   @t M
WHERE
   ISNUMERIC(M.Data) = 0
UNION ALL
SELECT
   M.UniqueID, M.ID, NULL
FROM
   @t M
   JOIN  --the <= JOIN gives us (M.Data) rows
   Nbrs N ON N.Number <= CASE WHEN ISNUMERIC(M.Data) = 1 THEN M.Data ELSE NULL END 
ORDER BY
   UniqueID
OPTION (MAXRECURSION 0)

Редактировать: JOIN был неправильно. К сожалению.

Числа CTE взяты из здесь

...