количество расписаний по дням недели - PullRequest
1 голос
/ 16 августа 2011

моя таблица выглядит следующим образом:

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' и т. Д.(но для удобства чтения я набрал их с помощью перевода строки):

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

Ответы [ 2 ]

2 голосов
/ 16 августа 2011
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]
0 голосов
/ 16 августа 2011

Это более многословно, но я сосредоточился (а) на том, чтобы избежать повторения выражений и (б) на моделировании всех входных параметров, предназначенных для передачи в хранимую процедуру, чтобы результаты фильтровались по желаемому пользователю / дате.Обратите внимание, что параметр @whichdate возвращается к предыдущей субботе в полночь, независимо от того, какой это день недели или какое время связано с ним.

Входные параметры:

DECLARE @whichdate DATETIME;
SET @whichdate = '2011-08-08T12:34:00';

DECLARE @whichforUID VARCHAR(32);
SET @whichforUID = 'user193';

Body (просто закомментируйте строки DECLARE @t / INSERT @t и замените @t в первом CTE на реальное имя таблицы:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...