SQL 两个日期之间的总小时数和 GROUP BY 列名?
SQL SUM hours between two dates & GROUP BY Column Name?
我需要像这样显示一个月内和之前一个月内某项操作所耗费的总小时数:
___________________________________________
| Rank | Action | Month | Prev Month |
|------|----------|------------|------------|
| 1 | Action1 | 580.2 | 200.7 |
| 2 | Action8 | 412.5 | 550.2 |
| 3 | Action10 | 405.0 | 18.1 |
---------------------------------------------
我有一个 SQL table 格式为:
_____________________________________________________
| Action | StartTime | EndTime |
|---------|---------------------|---------------------|
| Action1 | 2015-02-03 06:01:53 | 2015-02-03 06:12:05 |
| Action1 | 2015-02-03 06:22:16 | 2015-02-03 06:25:33 |
| Action2 | 2015-02-03 06:36:07 | 2015-02-03 06:36:49 |
| Action1 | 2015-02-03 06:36:46 | 2015-02-03 06:48:10 |
| ..etc | 20..-..-.. ...etc | 20..-..-.. ...etc |
-------------------------------------------------------
查询会是什么样子?
编辑:
A ツ 的回答让我朝着正确的方向前进,但是我使用 JOIN 解决了这个问题。请参阅下面的解决方案。
也许您应该检查预处理数据的使用分组,如下所示:
select Action, SUM(Hours)
from (select Action, DATEDIFF('hh',StartTime, EndTime) as Hours
FROM Actions)
group by Action
我的假设是你开始 - 结束时间跨度很短,你不必担心跨越 2 个月的日期,所以你可能需要这样的东西:
select
dense_rank() over (order by Month desc) as Rank,
action,
Month,
PrevMonth
from
(
select
action,
sum(case when StartTime >= @curMonth then hours else 0 end) as Month,
sum(case when StartTime >= @prevMonth and StartTime < @curMonth then hours else 0 end) as PrevMonth
from
(
select
action,
StartTime,
datediff(second, StartTime, EndTime) / 3600.0 as hours
from
yourtable
) T1
group by
action
) T2
这里计算的持续时间是秒,然后除以 3600 得到小时。排名仅基于当月。这预计您有 2 个变量 @curMonth 和 @prevMonth,它们具有限制的日期,并且没有未来的数据。
SQL Fiddle 用于测试:http://sqlfiddle.com/#!6/d64b7d/1
我稍微更改了值,因为只有一天很无聊
INSERT INTO yourtable
([Action], [StartTime], [EndTime])
VALUES
('Action1', '2015-02-18 06:01:53', '2015-02-18 06:12:05'),
('Action1', '2015-02-18 06:22:16', '2015-02-18 06:25:33'),
('Action2', '2015-04-03 06:36:07', '2015-04-03 06:36:49'),
('Action1', '2015-03-19 06:36:46', '2015-03-19 06:48:10'),
('Action2', '2015-04-13 06:36:46', '2015-04-13 06:48:10'),
('Action2', '2015-04-14 06:36:46', '2015-04-14 06:48:10')
;
现在定义日期边界:
declare @dateEntry datetime = '2015-04-03';
declare @date1 date
, @date2 date
, @date3 date;
set @date1 = @dateEntry; -- 2015-04-03
set @date2 = dateadd(month,-1,@date1); -- 2015-03-03
set @date3 = dateadd(month,-1,@date2); -- 2015-02-03
所选日期将包括在 2015-04-03 00:00 之前开始并在 2015-02-03 00:00
之后开始的所有操作
select date1 = @date1
, date2 = @date2
, date3 = @date3
, [Action]
, thisMonth =
sum(
case when Starttime between @date2 and @date1
then datediff(second, starttime, endtime)/360.0
end)
, lastMonth =
sum(
case when Starttime between @date3 and @date2
then datediff(second, starttime, endtime)/360.0
end)
from yourtable
where starttime between @date3 and @date1
group by [Action]
我只是在对 SQL 服务器进行了更多研究后才重新审视这个问题。
可以从一个查询创建一个临时 table,然后在另一个查询中使用 - 嵌套查询 如果您愿意。
这样,结果可以 JOIN
像通过任何其他正常 table 一样在一起,而没有令人讨厌的 CASE
语句。这对于显示第一个查询所需的其他数据也很有用,例如 COUNT(DISTINCT ColumnName)
JOIN two SELECT statement results
SELECT TOP 10
t1.Action, t1.[Time],
COALESCE(t2.[Time],0) AS [Previous Period 'Time'],
COALESCE( ( ((t1.[Time]*1.0) - (t2.[Time]*1.0)) / (t2.[Time]*1.0) ), -1 ) AS [Change]
FROM
(
SELECT
Action,
SUM(DATEDIFF(SECOND, StartTime, EndTime)) AS [Time],
FROM Actions
WHERE StartTime BETWEEN @start AND @end
GROUP BY Action
) t1
LEFT JOIN
(
SELECT
Action,
SUM(DATEDIFF(SECOND, StartTime, EndTime)) AS [Time]
FROM Actions
WHERE StartTime BETWEEN @prev AND @start
GROUP BY Action
) t2
ON
t1.Action = t2.Action
ORDER BY t1.[Time] DESC
希望此信息对某人有所帮助。
我需要像这样显示一个月内和之前一个月内某项操作所耗费的总小时数:
___________________________________________
| Rank | Action | Month | Prev Month |
|------|----------|------------|------------|
| 1 | Action1 | 580.2 | 200.7 |
| 2 | Action8 | 412.5 | 550.2 |
| 3 | Action10 | 405.0 | 18.1 |
---------------------------------------------
我有一个 SQL table 格式为:
_____________________________________________________
| Action | StartTime | EndTime |
|---------|---------------------|---------------------|
| Action1 | 2015-02-03 06:01:53 | 2015-02-03 06:12:05 |
| Action1 | 2015-02-03 06:22:16 | 2015-02-03 06:25:33 |
| Action2 | 2015-02-03 06:36:07 | 2015-02-03 06:36:49 |
| Action1 | 2015-02-03 06:36:46 | 2015-02-03 06:48:10 |
| ..etc | 20..-..-.. ...etc | 20..-..-.. ...etc |
-------------------------------------------------------
查询会是什么样子?
编辑:
A ツ 的回答让我朝着正确的方向前进,但是我使用 JOIN 解决了这个问题。请参阅下面的解决方案。
也许您应该检查预处理数据的使用分组,如下所示:
select Action, SUM(Hours)
from (select Action, DATEDIFF('hh',StartTime, EndTime) as Hours
FROM Actions)
group by Action
我的假设是你开始 - 结束时间跨度很短,你不必担心跨越 2 个月的日期,所以你可能需要这样的东西:
select
dense_rank() over (order by Month desc) as Rank,
action,
Month,
PrevMonth
from
(
select
action,
sum(case when StartTime >= @curMonth then hours else 0 end) as Month,
sum(case when StartTime >= @prevMonth and StartTime < @curMonth then hours else 0 end) as PrevMonth
from
(
select
action,
StartTime,
datediff(second, StartTime, EndTime) / 3600.0 as hours
from
yourtable
) T1
group by
action
) T2
这里计算的持续时间是秒,然后除以 3600 得到小时。排名仅基于当月。这预计您有 2 个变量 @curMonth 和 @prevMonth,它们具有限制的日期,并且没有未来的数据。
SQL Fiddle 用于测试:http://sqlfiddle.com/#!6/d64b7d/1
我稍微更改了值,因为只有一天很无聊
INSERT INTO yourtable
([Action], [StartTime], [EndTime])
VALUES
('Action1', '2015-02-18 06:01:53', '2015-02-18 06:12:05'),
('Action1', '2015-02-18 06:22:16', '2015-02-18 06:25:33'),
('Action2', '2015-04-03 06:36:07', '2015-04-03 06:36:49'),
('Action1', '2015-03-19 06:36:46', '2015-03-19 06:48:10'),
('Action2', '2015-04-13 06:36:46', '2015-04-13 06:48:10'),
('Action2', '2015-04-14 06:36:46', '2015-04-14 06:48:10')
;
现在定义日期边界:
declare @dateEntry datetime = '2015-04-03';
declare @date1 date
, @date2 date
, @date3 date;
set @date1 = @dateEntry; -- 2015-04-03
set @date2 = dateadd(month,-1,@date1); -- 2015-03-03
set @date3 = dateadd(month,-1,@date2); -- 2015-02-03
所选日期将包括在 2015-04-03 00:00 之前开始并在 2015-02-03 00:00
之后开始的所有操作select date1 = @date1
, date2 = @date2
, date3 = @date3
, [Action]
, thisMonth =
sum(
case when Starttime between @date2 and @date1
then datediff(second, starttime, endtime)/360.0
end)
, lastMonth =
sum(
case when Starttime between @date3 and @date2
then datediff(second, starttime, endtime)/360.0
end)
from yourtable
where starttime between @date3 and @date1
group by [Action]
我只是在对 SQL 服务器进行了更多研究后才重新审视这个问题。
可以从一个查询创建一个临时 table,然后在另一个查询中使用 - 嵌套查询 如果您愿意。
这样,结果可以 JOIN
像通过任何其他正常 table 一样在一起,而没有令人讨厌的 CASE
语句。这对于显示第一个查询所需的其他数据也很有用,例如 COUNT(DISTINCT ColumnName)
JOIN two SELECT statement results
SELECT TOP 10
t1.Action, t1.[Time],
COALESCE(t2.[Time],0) AS [Previous Period 'Time'],
COALESCE( ( ((t1.[Time]*1.0) - (t2.[Time]*1.0)) / (t2.[Time]*1.0) ), -1 ) AS [Change]
FROM
(
SELECT
Action,
SUM(DATEDIFF(SECOND, StartTime, EndTime)) AS [Time],
FROM Actions
WHERE StartTime BETWEEN @start AND @end
GROUP BY Action
) t1
LEFT JOIN
(
SELECT
Action,
SUM(DATEDIFF(SECOND, StartTime, EndTime)) AS [Time]
FROM Actions
WHERE StartTime BETWEEN @prev AND @start
GROUP BY Action
) t2
ON
t1.Action = t2.Action
ORDER BY t1.[Time] DESC
希望此信息对某人有所帮助。