2015-04-14 62 views
0

我之前需要它来显示这样的过去一个月内的动作与上月持平小时总量:两个日期&GROUP BY列名之间的SQL SUM小时数?

___________________________________________ 
| Rank | Action | Month | Prev Month | 
|------|----------|------------|------------| 
| 1 | Action1 |  580.2 |  200.7 | 
| 2 | Action8 |  412.5 |  550.2 | 
| 3 | Action10 |  405.0 |  18.1 | 
--------------------------------------------- 

我有一个SQL表的格式:

_____________________________________________________ 
| 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解决了这个问题。请参阅下面的解决方案。

+4

你能告诉我们你试图做到这一点吗? –

+1

你怎么知道哪个月?这是否会来自用户? –

+0

@wewesthemenace该月份将从日历日期小部件中输入,只有前10个结果将显示在生成的表格中。 – ChiMo

回答

1

我研究多一点关于SQL Server之后,刚刚重新审视这个问题。

可以从查询创建临时表,然后在另一个查询中使用 - 如果您愿意,可以使用嵌套查询
这样的结果可以像JOIN一样通过任何其他正常的表,而不会讨厌CASE声明。这也是有用的,以显示第一查询所需的其他DATAS像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 

希望这个信息是有用的人。

0

也许你应该检查在使用预处理的数据分组,像这样:

select Action, SUM(Hours) 
    from (select Action, DATEDIFF('hh',StartTime, EndTime) as Hours 
    FROM Actions) 
group by Action 
0

我的假设是,你开始 - 结束时间跨度很短,你不必担心跨日期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除以得到小时。排名仅基于当月。这期望你有两个变量@curMonth和@prevMonth,它们的限制日期是一样的,而且以后没有数据。

SQL小提琴来进行测试:http://sqlfiddle.com/#!6/d64b7d/1

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] 

http://sqlfiddle.com/#!6/35784/5

+0

你非常有帮助!我没有意识到你可以将CASE语句放在SUM字段中。唯一的问题是,即使当前月份的值为NULL(即收集上个月的数据),它也会收集所有结果。将WHERE子句设置为'WHERE(StartTime BETWEEN @ date2 AND @ date1)'从lastMonth'字段中删除数据并添加'WHERE thisMonth IS NOT NULL'不起作用,因为lastMonth不是有效的列名称_ – ChiMo

+0

NULL结果可能是在GROUP BY语句之后使用'HAVING'省略。但是为了显示正确的结果,需要重复'CASE'语句的SUM。 – ChiMo