我环顾四周,我也有类似的问题,购买我的用例略有不同。我可以管理基本的SQL,但可以使用一些工作。
所以我的用例是我有一个折线图报告,需要为其创建存储的proc。我有一个签到表,如下所示。我需要做的是计算每种位置类型所花费的时间,然后每周将其单独用于折线图。
我对饼图做了类似的事情。程序虽然不漂亮。
ALTER PROCEDURE [dbo].[sp_Report_TimeSpentAtBase]
@startdate as DateTime,
@endDate as DateTime = null,
@teamID as uniqueidentifier = null,
@userID as uniqueidentifier = null
AS
BEGIN
SELECT
LocationType,
Sum(DATEDIFF(minute, InAt, OutAt)) Seconds
FROM CheckIns
INNER JOIN Locations ON Locations.Id = CheckIns.Location_ID
INNER JOIN [System].[Users] ON CheckIns.User_Id = [System].[Users].Id
WHERE
DATEPART(dw, InAt) NOT IN (1, 7) AND
InAt >= @startdate AND
OutAt IS NOT NULL AND
DATEPART(dw, OutAt) NOT IN (1, 7) AND
(@teamID IS NULL OR [System].[Users].Team_ID = @teamID) AND
(@userID IS NULL OR [System].[Users].ID = @userID) AND
(@endDate IS NULL OR OutAt <= @endDate)
GROUP BY LocationType
END
GO
因此,为清楚起见,用户签入位置,我将其记录在签入表中。然后,我使用签入/签出时间来计算他们在该位置所花费的时间。我使用的折线图需要这种格式。
因此,理想情况下,我应该为每个位置类型都添加一个TimeSpentAtBaseRow,然后每个星期分配一个系列。
我不希望有人为我写这篇文章,我可以朝着正确的方向前进。感谢您的帮助或指导。
每个表格的数据示例:
位置类型只是一个枚举
和签到表
最后,现有存储过程的结果如下:
LocationType | Minutes
----------------------
Base | 100
Hospital | 200
所以每种位置类型的每次签到的总分钟数。
编辑
所以我目前的进展是
WITH dates as
(
select number, DATEADD(day, number, '20170101') as dt
from master..spt_values
where number between 0 and 1000 AND TYPE ='P'
)
SELECT
l.LocationType,
d.dt,
Sum(DATEDIFF(minute, InAt, OutAt)) as mins
FROM Checkins ci
INNER JOIN Locations l ON l.Id = ci.Location_ID
JOIN dates d
on d.dt between ci.InAt and ci.OutAt
GROUP BY
d.dt, l.LocationType
答案 0 :(得分:1)
这是一般想法。对于边缘情况,边界检查可能需要一些调整。
/*
Set up data
*/
declare @startDate datetime = '07/01/2018'; -- first day you want included
declare @endDate datetime = '07/15/2018'; -- day AFTER the last you want included
declare @location table (locationId int, locationName varchar(100));
declare @log table (logId int, locationId int, checkIn datetime, checkOut datetime);
insert @location values
(1, 'Location 1'),
(2, 'Location 2');
insert @log values
(1, 1, '07/07/2018 20:00:00', '07/08/2018 06:00:00'),
(2, 1, '07/08/2018 20:00:00', '07/09/2018 06:00:00'),
(3, 1, '07/09/2018 20:00:00', '07/10/2018 06:00:00')
;
/*
Summary by location
*/
select loc.locationId ,
loc.locationName ,
SUM(DATEDIFF(MINUTE, log.checkIn, log.checkOut)) as minutes
from @location loc
inner join @log log on log.locationId = loc.locationId
group by loc.locationId ,
loc.locationName
;
/*
Summary by location and week
*/
with
-- List of weeks. There are other ways to do this.
weeks as (
select @startDate as startDate ,
dateadd(week, 1, @startDate) as endDate
union all
select endDate /*as startDate*/ ,
dateadd(week, 1, endDate) /* as endDate*/
from weeks
where endDate < @endDate
) ,
-- Determine how much time each log entry is in each week.
logWeeks as (
select log.locationId ,
w.startDate as week ,
datediff(
minute ,
case when log.checkIn >= w.startDate then log.checkIn else w.startDate end ,
case when log.checkOut <= w.endDate then log.checkOut else w.endDate end
) as minutes
from @log log
inner join weeks w
on log.checkIn < w.endDate
and log.checkOut >= w.startDate
)
-- Summarize.
select loc.locationId ,
loc.locationName ,
lw.week ,
sum(lw.minutes)
from @location loc
inner join logWeeks lw
on lw.locationId = loc.locationId
group by loc.locationId ,
loc.locationName ,
lw.week
order by loc.locationId ,
lw.week
;
答案 1 :(得分:0)
下面是我为要求创建的解决方案,该解决方案将日期范围分为给定的时间间隔(不包括周末)。
我创建了1个将日期范围划分为给定间隔的过程。 另外,创建了一种方法来检查日期是否为周末,并根据标志值返回下一个/上一个工作日。
下面是过程
<footnotes>
<footnote id="F1">content1</footnote>
<footnote id="F2">content2</footnote>
<footnote id="F3">content3</footnote>
<footnote id="F4">content4</footnote>
</footnotes>
检查周末并将其转换为工作日的方法
import csv
from bs4 import BeautifulSoup
with open('output.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile, )
soup = BeautifulSoup(doc, 'htmparser') #Let's say doc has the html.
Footnotes = soup.select('footnotes')
Footnotes = '/'.join(Footnotes)
writer.writerow(Footnotes.text)