Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 对于包含数据的每一行,我需要每个类别对应一行_Sql_Sql Server_Sql Server 2012 - Fatal编程技术网

Sql 对于包含数据的每一行,我需要每个类别对应一行

Sql 对于包含数据的每一行,我需要每个类别对应一行,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我有时间表数据,需要为“按日期范围”创建报告。我需要为每个人每天和每种时间类型排一行。如果给定的一天中没有该时间类型的条目,则我需要空数据。我试过左键连接,但似乎不起作用。交叉连接将给出错误的数据 我拥有的表是Person表personID、Name、TimeLog表TimeLogID、StartDate、EndDate、TimeLogTypeID和TimeLogType表TimeLogTypeID、personID、Description、DeletedInd 我在结果集中只能得到包含数据的行

我有时间表数据,需要为“按日期范围”创建报告。我需要为每个人每天和每种时间类型排一行。如果给定的一天中没有该时间类型的条目,则我需要空数据。我试过左键连接,但似乎不起作用。交叉连接将给出错误的数据

我拥有的表是Person表personID、Name、TimeLog表TimeLogID、StartDate、EndDate、TimeLogTypeID和TimeLogType表TimeLogTypeID、personID、Description、DeletedInd

我在结果集中只能得到包含数据的行,而不是每个TimeLogType的空行

以下是我目前掌握的情况:

DECLARE 
    @startDate  DATE,
    @endDate    DATE

SET @startDate = '2014-05-01'
SET @endDate =   '2014-05-30'

SELECT
    CONVERT(DATE, TimeLog.StartDateTime, 101) AS TimeLogDay,
    SUM(dbo.fnCalculateHoursAsDecimal(TimeLog.StartDateTime, TimeLog.EndDateTime)) AS Hours,
    TimeLog.PersonID,
    TimeLog.TimeLogTypeID

INTO #HourTable

FROM
    TimeLog

WHERE   
    TimeLog.StartDateTime BETWEEN @startDate AND @endDate

GROUP BY
    CONVERT(DATE, TimeLog.StartDateTime, 101),
    TimeLog.TimeLogTypeID,  
    TimeLog.PersonID

SELECT 
    TimeLogType.Description,    
    #HourTable.*
FROM 
    TimeLogType LEFT JOIN
    #HourTable ON TimeLogType.TimeLogTypeID = #HourTable.TimeLogTypeID

WHERE 
    ISNULL(TimeLogType.DeletedInd, 0) = 0

ORDER BY
    PersonID, TimeLogDay, TimeLogType.TimeLogTypeID
数据如下所示:

with dates as (
      select dateadd(day, number - 1, mind) as thedate
      from (select min(StartDate) as mind, max(EndDate) as endd
            from TimeLogType
           ) tlt join
           master..spt_values v
           on dateadd(day, v.number, mind) <= tlt.endd
     )
select p.PersonId, tlt.TimeLogTypeId, d.thedate, 
from Person p cross join
     (select tlt.* from TimeLogType tlt where ISNULL(TimeLogType.DeletedInd, 0) = 0
     ) tlt cross join
     date d left join
     TimeLog tl
     on tl.Person_id = p.PersonId and tl.TimeLogTypeId = tlt.TimeLogTypeId and
        d.thedate >= tl.StartDate and d.thedate <= tl.EndDate
时间日志类型: 1、计费 2、不计费

人: 1,比利 2、汤姆

时间日志: 1, 1, 2014-05-01 08:00:00, 2014-05-01 09:00:00, 1, 0 2, 1, 2014-05-01 09:00:00, 2014-05-01 10:00:00, 1, 0 3, 2, 2014-05-01 08:00:00, 2014-05-01 08:30:00, 2, 0 4, 2, 2014-05-01 08:30:00, 2014-05-01 09:00:00, 1, 0 5,1,2014-05-02 08:00:00,2014-05-02 09:00:00,2,0

预期输出:按人员、日期、时间记录类型排序 天、人、账单类型、总小时数 2014-05-01,比利,可付费,2.0 2014-05-01,比利,不计费,无效 2014-05-02,比利,可付费,1.0 2014-05-02,比利,不可付费,无效 等 2014年5月1日,汤姆,应纳税,0.5 2014-05-01,汤姆,不收费,0.5
等等

您需要首先生成所有组合,然后使用left join输入所需的信息。我认为问题是这样的:

with dates as (
      select dateadd(day, number - 1, mind) as thedate
      from (select min(StartDate) as mind, max(EndDate) as endd
            from TimeLogType
           ) tlt join
           master..spt_values v
           on dateadd(day, v.number, mind) <= tlt.endd
     )
select p.PersonId, tlt.TimeLogTypeId, d.thedate, 
from Person p cross join
     (select tlt.* from TimeLogType tlt where ISNULL(TimeLogType.DeletedInd, 0) = 0
     ) tlt cross join
     date d left join
     TimeLog tl
     on tl.Person_id = p.PersonId and tl.TimeLogTypeId = tlt.TimeLogTypeId and
        d.thedate >= tl.StartDate and d.thedate <= tl.EndDate

在阅读了戈登的答案后,我想到了这一点。我一步一步地创建了它,这样我就可以看到发生了什么。我创建了没有主..spt_值表的日期。我还创建了一个临时人员表,这样我就可以只选择那些有TimeLogRecord的人员,然后重新使用它来获取最终选择的详细信息。让我知道是否有任何方法可以让这跑得更快

DECLARE 
    @startDate  DATE,
    @endDate    DATE

SET @startDate = '2014-01-01'
SET @endDate =   '2014-01-31'

-- create day rows --
;WITH dates(TimeLogDay) AS 
(
    SELECT @startDate AS TimeLogDay
    UNION ALL
    SELECT DATEADD(d, 1, TimeLogDay)
    FROM dates 
    WHERE TimeLogDay < @enddate
)

-- create a type row for each day --
SELECT
    dates.TimeLogDay,
    tlt.TimeLogTypeID

INTO #TypeDate

FROM 
    dates CROSS JOIN 
    (SELECT
        TimeLogType.TimeLogTypeID
     FROM 
        TimeLogType 
     WHERE 
        ISNULL(TimeLogType.DeletedInd, 0) = 0
    ) AS TLT 

-- create a temp person table for referance later ---
SELECT * INTO #person FROM Person WHERE Person.personID IN 
        (SELECT Timelog.PersonID FROM TimeLog WHERE TimeLog.StartDateTime BETWEEN @startDate AND @endDate)

-- sum up the log times and tie in the date/type rows --
SELECT  
    #TypeDate.TimeLogDay,
    #TypeDate.TimeLogTypeID,
    #person.PersonID,
    SUM(dbo.fnCalculateHoursAsDecimal(TimeLog.StartDateTime, TimeLog.EndDateTime)) AS Hours

INTO #Hours

FROM
    #person CROSS JOIN
    #TypeDate LEFT JOIN
    TimeLog ON
        TimeLog.PersonID = #person.PersonID AND
        TimeLog.TimeLogTypeID = #TypeDate.TimeLogTypeID AND
        #TypeDate.TimeLogDay = CONVERT(DATE, TimeLog.StartDateTime, 101)

GROUP BY
    #TypeDate.TimeLogDay,
    #TypeDate.TimeLogTypeID,
    #person.PersonID

-- now tie in the details to complete --
SELECT
    #Hours.TimeLogDay,
    TimeLogType.Description,
    Person.LastName,
    Person.FirstName,
    #Hours.Hours

FROM
    #Hours LEFT JOIN
    Person ON #Hours.PersonID = Person.PersonID LEFT JOIN
    TimeLogType ON #Hours.TimeLogTypeID = TimeLogType.TimeLogTypeID

ORDER BY
    Person.FirstName,
    Person.LastName,
    #Hours.TimeLogDay,
    TimeLogType.SortOrder

你能给出表格中的示例数据吗?还有一个简短但描述性的预期输出示例。我发现CTE有一些语法错误。我不得不把主人。。在spt_值表前面,在联接之前的子选择中将别名从“v”更改为“dte”,但行选择dateaddday,数字-1,mindate,因为该日期在mindate上给了我一个错误part@user3033282 . . . 很抱歉。现在试试看。