Domanda

Started with TSQL last Wednesday...

I have the following data in tblStage1:

PROJECT    USERNAME           DATE          PERCENTAGE                  
---------  -----------------  ------------  ---------------------- 
Project 1  DOMAIN\Chris.User  03/01/2013    0.25                     
Project 1  DOMAIN\Chris.User  05/01/2013    0.75                     
Project 1  DOMAIN\Chris.User  07/01/2013    1                     
Project 1  DOMAIN\John.User   02/01/2013    1                     
Project 1  DOMAIN\John.User   06/01/2013    0.5                     

I have the following data in tblRawData

PROJECT    START_DATE   END_DATE
---------- -----------  ----------
Project 1  01/01/2013   09/01/2013

I would like to get the following data out into tblStage2 (data points are bound by START_DATE and END_DATE):

PROJECT    USERNAME           DATE          PERCENTAGE                  
---------  -----------------  ------------  ---------------------- 
Project 1  DOMAIN\Chris.User  01/01/2013    0                     
Project 1  DOMAIN\Chris.User  02/01/2013    0                         
Project 1  DOMAIN\Chris.User  03/01/2013    0.25                     
Project 1  DOMAIN\Chris.User  04/01/2013    0.25                      
Project 1  DOMAIN\Chris.User  05/01/2013    0.75                     
Project 1  DOMAIN\Chris.User  06/01/2013    0.75                     
Project 1  DOMAIN\Chris.User  07/01/2013    1                     
Project 1  DOMAIN\Chris.User  08/01/2013    1                     
Project 1  DOMAIN\Chris.User  09/01/2013    1                  
Project 1  DOMAIN\John.User   01/01/2013    0                     
Project 1  DOMAIN\John.User   02/01/2013    1                         
Project 1  DOMAIN\John.User   03/01/2013    1
Project 1  DOMAIN\John.User   04/01/2013    1                      
Project 1  DOMAIN\John.User   05/01/2013    1                     
Project 1  DOMAIN\John.User   06/01/2013    0.5                     
Project 1  DOMAIN\John.User   07/01/2013    0.5                     
Project 1  DOMAIN\John.User   08/01/2013    0.5                     
Project 1  DOMAIN\John.User   09/01/2013    0.5                  

I realize that there are a number of topics that relate to this subject such as this. I my case, I don't have any particular restrictions and I am looking for a clean routine that is relatively easy to understand.

I know there is a DateAdd function, but I haven't seen any INSERT INTO commands in the example statements. I am confused as to how one would iterate through the data set and create the interpolated values. I am still too green to understand the full context of the other examples and would greatly appreciate any help or clarification.

Edit Added additional information to the sample data for a better indication of my final goal. I will have multiple users in this data set. The USERNAME column is placed into the data set by the original source (a people picker on an InfoPath form). All "Percentages" are "0" until the first value is assigned then they retain that value until it is changed or the project reaches its end date. I hope this helps clarify!

È stato utile?

Soluzione

It's not clear how USERNAME populated. I assume you have same USERNAME on project here. CTE below just build a DATE table, if you have your own date table, you can skip this part.

SQL Fiddle

DECLARE @ENDDate DATETIME

SELECT @ENDDate =  MAX(END_DATE) FROM tblRawData

;WITH tblDate AS 
( SELECT CAST(MIN(START_DATE) AS DATE) AS [date]
  FROM tblRawData 
  UNION ALL
  SELECT DATEADD(month,1,[DATE])
  FROM tblDate
  WHERE [DATE] < @ENDDate
 )
SELECT
  d.[date]
  ,r.[Project]
  ,UserName =   (SELECT MAX(USERNAME) FROM tblStage1 ts WHERE r.PROJECT = ts.PROJECT)
  ,Percentage = (SELECT ISNULL(MAX(Percentage),0) FROM tblStage1 ts WHERE r.PROJECT = ts.PROJECT AND ts.[date] <= d.[date])
FROM tblDate d
INNER JOIN tblRawData r
  ON d.[date] between r.[START_DATE] AND r.[END_DATE]
ORDER BY 2,1
OPTION (Maxrecursion 0) 

EDIT: Just found out the date is increased by month. I update the CTE query. However, you need make sure you have all project start and end date at first day of the month.


EDIT Base on your new sample date. the query became a little ugly now, however, it works. I can not think better solution right now.

New SQL Fiddler

DECLARE @ENDDate DATETIME

SELECT @ENDDate =  MAX(END_DATE) FROM tblRawData

;WITH tblDate AS 
( SELECT CAST(MIN(START_DATE) AS DATE) AS [date]
  FROM tblRawData 
  UNION ALL
  SELECT DATEADD(month,1,[DATE])
  FROM tblDate
  WHERE [DATE] < @ENDDate
 )
,ProjectList AS (
 SELECT Project,UserName
 FROM tblStage1
 GROUP BY Project,UserName
)
,cte AS (
SELECT
  d.[date]
  ,r.[Project]
  ,UserName = pl.Username
  ,CloseDate = (SELECT MAX(ts.[date]) FROM tblStage1 ts WHERE r.PROJECT = ts.PROJECT AND ts.UserName = pl.UserName AND ts.[date] <= d.[date])
FROM tblDate d
INNER JOIN tblRawData r
  ON d.[date] between r.[START_DATE] AND r.[END_DATE]
CROSS APPLY ProjectList pl
)
SELECT cte.[date],cte.project,cte.UserName,ISNULL(t.[PERCENTAGE],0) AS PERCENTAGE
FROM cte
LEFT JOIN tblStage1 t
 ON cte.PROJECT = t.PROJECT 
  AND cte.UserName = t.UserName  
  AND cte.CloseDate = t.[Date]
ORDER BY 2,3,1

Altri suggerimenti

You could do this with the APPLY operator as well...

WITH DateList (Project, MonthStart) AS
    (
        SELECT 
            project
            , Start_Date
        FROM 
            tblRawData
        UNION ALL
        SELECT 
            dl.Project
            , DATEADD(MONTH, 1, dl.MonthStart)
        FROM 
            DateList dl
        JOIN
            tblRawData r 
            ON 
                r.Project = dl.Project
                AND 
                dl.MonthStart < r.End_Date
    )
SELECT 
    dl.Project
    , lastUser.UserName 
    , dl.monthstart [Date]
    , ISNULL(pct.Percentage, 0) Percentage
FROM 
    DateList dl
CROSS APPLY
    (
        SELECT 
            TOP 1 
            USERNAME
        FROM
            tblStage1 t1
        WHERE 
            t1.Project = dl.Project
        ORDER BY 
            t1.Date DESC
    ) lastUser
OUTER APPLY
    (
        SELECT 
            TOP 1 
            Percentage
        FROM
            tblStage1 t2
        WHERE 
            t2.Project = dl.Project
            AND 
            t2.Date <= dl.MonthStart
        ORDER BY 
            t2.Date DESC
    ) pct

A really easy way would be to create a temp table with the month values of each month you need then doing a left join on that table.

Out of curiosity - why is August 1 instead of 0?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top