2015-09-21 3 views
1

У меня есть строки в databasetable, который на следующей форме:Split строки на несколько с SQL заявления

ID | Amount | From  | To 
5 | 5439 | 01.01.2014 | 05.01.2014 

Я хочу разделить это до одного ряда пр месяц, используя SQL/T-SQL:

Amount | From  
5439 | 01.01.2014 
5439 | 02.01.2014 
5439 | 03.01.2014 
5439 | 04.01.2014 
5439 | 05.01.2014 

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

Edit: После запросов на моем коде, я попытался следующие:

declare @counter int 
set @counter = 0 
WHILE @counter < 6 
begin 
    set @counter = @counter +1 
    select amount, DATEADD(month, @counter, [From]) as Dato 
    FROM [database].[dbo].[table] 
end 

Это, однако, возвращает несколько databasesets.

+3

Я полагаю, вам понадобится таблица календаря помощи, чтобы присоединиться. – jarlh

+3

Где ваш код! что вы уже пробовали? – Marusyk

+0

Вы попробовали рекурсивный запрос? https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx –

ответ

4

Вы можете использовать tally table для создания всех дат.

SQL Fiddle

;WITH E1(N) AS(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
), 
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), 
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), 
Tally(N) AS(
    SELECT TOP(SELECT MAX(DATEDIFF(DAY, [From], [To])) + 1 FROM yourTable) 
     ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
    FROM E4 
) 
SELECT 
    yt.Id, 
    yt.Amount, 
    [From] = DATEADD(DAY, N-1, yt.[From]) 
FROM yourTable yt 
CROSS JOIN Tally t 
WHERE 
    DATEADD(DAY, N-1, yt.[From]) <= yt.[To] 

Simplified explanation on Tally Table

2

Вам нужна таблица индикаторную с "бегущих чисел". Это может быть функция (я опубликовал ее коротко здесь: https://stackoverflow.com/a/32096945/5089204) или физическую таблицу (здесь я привел пример: https://stackoverflow.com/a/32474751/5089204) или CTE, чтобы сделать это «на лету» (пример таблицы делает это таким образом).

Если вы идете с публикуемыми функциями это может быть так:

declare @startDate DATETIME={d'2015-09-01'}; 
declare @EndDate DATETIME={d'2015-09-10'}; 
select DATEADD(DAY, Nmbr,@startDate) 
from dbo.GetRunningNumbers(DATEDIFF(DAY,@startDate,@endDate)+1,0); 
2
select * INTO #TEMP1 from 
(values 
(5 , 5439 , '01.01.2014', '05.01.2014'))t(id,amount,fromd,tod) 

WITH CTE 
AS 
(
    SELECT CAST(FROMD AS DATE) AS FROMD,amount,1 AS RN,ID FROM #TEMP1 
    UNION ALL 
    SELECT DATEADD(M,1,C.FROMD),C.amount,C.RN+1,C.ID 
    FROM CTE C 
      INNER JOIN #TEMP1 T ON T.id = C.ID AND DATEADD(M,1,c.FROMD)<=T.tod 

) 

SELECT * FROM CTE 
2
create table t (fd date, td date) 
insert into t values ('2015-01-01','2015-01-05') 

WITH DATES (fd, td, Level) 
AS 
(
    SELECT fd, td, 0 AS Level 
    FROM t 
    UNION ALL 
-- Recursive member definition 
    SELECT DATEADD(day,level+1,e.fd),e.td,Level + 1 
    FROM t AS e 
    INNER JOIN Dates AS d ON DATEADD(day,-d.level,d.fd) = e.fd AND d.fd < d.td 

) 
-- Statement that executes the CTE 
SELECT fd,td,level 
from DATES 
1

варианта с использованием рекурсивных ОТВ

--variable table for data sample 
DECLARE @tbl AS TABLE 
    (
     ID INT , 
     Amount FLOAT , 
     [From] DATE , 
     [To] DATE 
    ) 
INSERT INTO @tbl 
     (ID, Amount, [From], [To]) 
VALUES (5, 5439, '2014-01-01', '2014-01-05') 

--final query using recursive cte 
; 
WITH cte 
      AS (SELECT T.ID , 
         T.Amount , 
         T.[From] , 
         T.[To] , 
         CONVERT(DATE, NULL) AS Dt , 
         n = 0 
       FROM  @tbl AS T 
       UNION ALL 
       SELECT cte.ID , 
         cte.Amount , 
         cte.[From] , 
         cte.[To] , 
         DATEADD(DAY, n, cte.[From]) , 
         cte.n + 1 
       FROM  cte 
       WHERE n <= DATEDIFF(day, cte.[From], cte.[To]) 
      ) 
    SELECT cte.ID , 
      cte.Amount , 
      dt AS [From] 
    FROM cte 
    WHERE cte.Dt IS NOT NULL 


SQL Fiddle

Смежные вопросы