我的考勤数据列表如下所示。现在,我试图按特定日期范围(2016年5月1日 - 2016年5月7日)查找数据,总有效列,总有效列将根据以前的当前数据(P)计算。假设今天是2016年5月4日。如果一个人有01,02,03,04状态'p',那么它将显示04-05-2016总日期4。
你能帮我从这个结果集中找到总数吗?
答案 0 :(得分:6)
您可以查看此示例,该示例具有计算先前总和值的逻辑。
declare @t table (employeeid int, datecol date, status varchar(2) )
insert into @t values (10001, '01-05-2016', 'P'),
(10001, '02-05-2016', 'P'),
(10001, '03-05-2016', 'P'),
(10001, '04-05-2016', 'P'),
(10001, '05-05-2016', 'A'),
(10001, '06-05-2016', 'P'),
(10001, '07-05-2016', 'P'),
(10001, '08-05-2016', 'L'),
(10002, '07-05-2016', 'P'),
(10002, '08-05-2016', 'L')
--select * from @t
select * ,
SUM(case when status = 'P' then 1 else 0 end) OVER (PARTITION BY employeeid ORDER BY employeeid, datecol
ROWS BETWEEN UNBOUNDED PRECEDING
AND current row)
from
@t
通过cte的同一件事的另一个转折(正如您编写的SQLSERVER2012,此解决方案仅适用于Sqlserver 2012及更高版本)
;with cte as
(
select employeeid , datecol , ROW_NUMBER() over(partition by employeeid order by employeeid, datecol) rowno
from
@t where status = 'P'
)
select t.*, cte.rowno ,
case when ( isnull(cte.rowno, 0) = 0)
then LAG(cte.rowno) OVER (ORDER BY t.employeeid, t.datecol)
else cte.rowno
end LagValue
from @t t left join cte on t.employeeid = cte.employeeid and t.datecol = cte.datecol
order by t.employeeid, t.datecol
答案 1 :(得分:2)
您可以使用子查询为每行计算TotalPresent
:
SELECT
main.EmployeeID,
main.[Date],
main.[Status],
(
SELECT SUM(CASE WHEN t.[Status] = 'P' THEN 1 ELSE 0 END)
FROM [TableName] t
WHERE t.EmployeeID = main.EmployeeID AND t.[Date] <= main.[Date]
) as TotalPresent
FROM [TableName] main
ORDER BY
main.EmployeeID,
main.[Date]
这里我使用子查询来计算具有相同EmployeeID
且日期小于或等于当前行日期的记录总和。如果记录的状态为&#39; P&#39;,则将1添加到总和,否则为0,它仅计算具有状态P的记录。
答案 2 :(得分:2)
有趣的问题,这应该有效:
select *
, (select count(retail) from p g
where g.date <= p.date and g.id = p.id and retail = 'P')
from p
order by ID, Date;
所以我相信我理解正确。您希望按日期计算每个ID的出现次数。
这很有道理。这就是为什么ID2的第一次出现是L而且Total是0.这个查询将计算每次出现的P状态,对于每个ID暂停非P..