我的表看起来像这样:
select clocktime, for_UID, in1_out0 from timeclockentries
clocktime for_UID in1_out0
2011-08-07 15:13:58.390 user193 1
2011-08-07 21:09:45.093 user193 0
2011-08-09 14:10:00.000 user193 1
2011-08-09 20:10:00.000 user193 0
我希望结果看起来像(假设周开始是星期六),由名为'day1','day2'等的COLUMNS分隔....(但为了便于阅读,我用换行符输入了它们) :
day1 day2 day3
1900-01-01 00:00:00.000 1900-01-01 05:55:46.700 1900-01-01 00:00:00.000
day4 day5 day6
1900-01-01 06:00:00.000 1900-01-01 00:00:00.000 1900-01-01 00:00:00.000
day7
1900-01-01 00:00:00.000
(我正在使用sql2005)
下面是我正在使用的一天:CREATE PROCEDURE [dbo].[sp_gethoursbyday]
@whichforUID varchar(20),
@whichdate datetime
AS
BEGIN
;WITH CTE as(
SELECT
DENSE_RANK() over (Partition by for_UID , in1_out0 Order by clocktime) id,
clocktime,
for_UID,
in1_out0
FROM
kdhcastle.dbo.timeclockentries tc
WHERE
tc.for_UID = @whichforUID
and month(tc.[clocktime]) = month(@whichdate)
and day(tc.[clocktime]) = day(@whichdate)
and year(tc.[clocktime]) = year(@whichdate)
)
SELECT
Cast(cast(sum(
cast(outTime.clocktime as float) - cast(inTime.clocktime as float)
)as datetime) as datetime) as 'hoursbydy'
FROM
CTE inTime
INNER JOIN CTE outTime
ON inTime.for_UID = outTime.for_UID
AND inTime.id = outTime.id
AND inTime.in1_out0 = 1
and outTime.in1_out0 = 0
END
答案 0 :(得分:2)
SELECT
SUM(CASE WHEN DayOfWeek = 1 THEN Duration ELSE 0 END) AS Day1,
SUM(CASE WHEN DayOfWeek = 2 THEN Duration ELSE 0 END) AS Day2,
SUM(CASE WHEN DayOfWeek = 3 THEN Duration ELSE 0 END) AS Day3,
SUM(CASE WHEN DayOfWeek = 4 THEN Duration ELSE 0 END) AS Day4,
SUM(CASE WHEN DayOfWeek = 5 THEN Duration ELSE 0 END) AS Day5,
SUM(CASE WHEN DayOfWeek = 6 THEN Duration ELSE 0 END) AS Day6,
SUM(CASE WHEN DayOfWeek = 7 THEN Duration ELSE 0 END) AS Day7
FROM
(
SELECT
DATEDIFF(DAY, '2011 Jan 01', clocktime) % 7 + 1 AS DayOfWeek,
CAST(MAX(clocktime) - MIN(clocktime) AS FLOAT) AS Duration
FROM
yourTable
GROUP BY
for_UID,
DATEDIFF(DAY, '2011 Jan 01', clocktime)
)
AS [data]
答案 1 :(得分:0)
这更详细但我的重点是(a)避免重复表达式和(b)模拟要输入到存储过程的所有输入参数,以便在所需的用户/日期过滤结果。请注意,@whichdate参数会在午夜回归到前一个星期六,无论一周中的哪一天或与之相关的时间。
输入参数:
DECLARE @whichdate DATETIME;
SET @whichdate = '2011-08-08T12:34:00';
DECLARE @whichforUID VARCHAR(32);
SET @whichforUID = 'user193';
正文(只需注释掉DECLARE @t / INSERT @t行,并将第一个CTE中的@t更改为实际表名:
SET @whichdate = DATEADD(DAY, -DATEPART(WEEKDAY, @whichdate), @whichdate);
SET @whichdate = DATEADD(DAY, 0, DATEDIFF(DAY, 0, @whichdate));
DECLARE @t TABLE(clocktime DATETIME, for_UID VARCHAR(32), in1_out0 BIT);
INSERT @t SELECT '2011-08-07 15:13:58.390','user193',1
UNION ALL SELECT '2011-08-07 21:09:45.093','user193',0
UNION ALL SELECT '2011-08-09 14:10:00.000','user193',1
UNION ALL SELECT '2011-08-09 20:10:00.000','user193',0;
WITH s(dw, ct, in1_out0) AS
(
SELECT 1 + (DATEDIFF(DAY, '2011-01-01', clocktime) % 7),
clocktime, in1_out0 FROM @t
where for_UID = @whichforUID
AND clocktime >= @whichdate
AND clocktime < DATEADD(DAY, 7, @whichdate)
),
d(dw, min_ct, max_ct) AS
(
SELECT dw,
MIN(CASE WHEN in1_out0 = 1 THEN ct ELSE NULL END),
MAX(CASE WHEN in1_out0 = 0 THEN ct ELSE NULL END)
FROM s GROUP BY dw
),
x AS
(
SELECT d = DATEADD(MILLISECOND, DATEDIFF(MILLISECOND, min_ct, max_ct), 0),
dw FROM d
),
pvt AS (
SELECT * FROM x PIVOT
(MAX(d) FOR dw IN ([1],[2],[3],[4],[5],[6],[7])) AS p
)
SELECT
day1 = COALESCE([1], '19000101'),
day2 = COALESCE([2], '19000101'),
day3 = COALESCE([3], '19000101'),
day4 = COALESCE([4], '19000101'),
day5 = COALESCE([5], '19000101'),
day6 = COALESCE([6], '19000101'),
day7 = COALESCE([7], '19000101')
FROM pvt;