SUM()同一数据集中的多个日期

时间:2018-09-24 09:29:15

标签: sql tsql reporting-services sql-server-2016

我需要一些有关如何解决报表查询问题的想法。
正在使用3列,均在同一表中,分别为“ EventDate”,“ Distance”和“ EventName”。 对于已注册的每个事件,事件的时间和日期都会与“ EventName”一起记录。
我需要查询执行的操作是计算所谓的主要事件之间的SUM(Distance),主要事件具有设置的名称,但一天可能多次发生。

我想不出一种写使用“ EventDate”的查询的方法,其中“ EventName” =“某物”,然后继续进行直到到达“ EventName” =“某物”,然后给出SUM(Distance),然后重新开始从下一个“ EventName” =“ something”开始,直到数据集中不再有“ EventName” =“ something”的记录为止。

很抱歉,如果让您感到困惑,请多多帮助或帮助我解决此问题的代码段。

    EventName              EventDate                Distance
    All Clear              2018-09-06 01:54:00.000  0
    Passing 3 Nmz          2018-09-06 02:35:00.000  0
    Commence Sea Passage   2018-09-06 03:00:00.000  10
    Commence Sea Passage   2018-09-06 03:00:00.000  0
    DailyReport            2018-09-06 12:00:00.000  119
    End Of Sea Passage     2018-09-07 05:45:00.000  335
    Pilot Embarked         2018-09-07 06:00:00.000  0
    Tug Fast               2018-09-07 07:40:00.000  0
    Mooring Commenced      2018-09-07 08:15:00.000  0
    All Fast               2018-09-07 08:45:00.000  19
    Pilot Embarked         2018-09-07 23:18:00.000  0
    Unmooring Commenced    2018-09-07 23:45:00.000  0
    All Clear              2018-09-08 00:00:00.000  0,01
    Pilot Disembarked      2018-09-08 01:30:00.000  0
    Commence Sea Passage   2018-09-08 01:40:00.000  17
    Voyage Complete        2018-09-08 01:40:00.000  0
    Voyage Commenced       2018-09-08 01:45:00.000  0
    End Of Sea Passage     2018-09-08 10:00:00.000  83
    Anchored               2018-09-08 11:00:00.000  3,2
    DailyReport            2018-09-08 12:00:00.000  0
    All Fast               2018-09-09 20:00:00.000  40

在上述数据集上,我希望与“ All Clear”(包括“ All Fast”)保持距离。

2 个答案:

答案 0 :(得分:1)

这听起来像是一个空白与孤岛的问题。

您可以根据事件类型生成排名。
然后对那个等级进行分组,并计算出与之的总距离。

示例代码段

-- Using a table variable for testing purposes
declare @Table table (EventDate datetime, EventName varchar(30), Distance decimal(9,2));

-- Sample data
insert into @Table (EventName, EventDate, Distance) values
 ('All Clear','2018-09-06 01:54',0)
,('Passing 3 Nmz','2018-09-06 02:35',0)
,('Commence Sea Passage','2018-09-06 03:00',10)
,('Commence Sea Passage','2018-09-06 03:00',0)
,('DailyReport','2018-09-06 12:00',119)
,('End Of Sea Passage','2018-09-07 05:45',335)
,('Pilot Embarked','2018-09-07 06:00',0)
,('Tug Fast','2018-09-07 07:40',0)
,('Mooring Commenced','2018-09-07 08:15',0)
,('All Fast','2018-09-07 08:45',19)
,('Pilot Embarked','2018-09-07 23:18',0)
,('Unmooring Commenced','2018-09-07 23:45',0)
,('All Clear','2018-09-08 00:00',0.01)
,('Pilot Disembarked','2018-09-08 01:30',0)
,('Commence Sea Passage','2018-09-08 01:40',17)
,('Voyage Complete','2018-09-08 01:40',0)
,('Voyage Commenced','2018-09-08 01:45',0)
,('End Of Sea Passage','2018-09-08 10:00',83)
,('Anchored','2018-09-08 11:00',3.2)
,('DailyReport','2018-09-08 12:00',0)
,('All Fast','2018-09-09 20:00',40)
;

-- Query
;with CTE as
(
  select EventDate, Distance, EventName
   , iif(EventName = 'All Clear',1,0) as isMainEvent
  from @Table
)
select 
 min(EventDate) as MinDateTime,
 max(EventDate) as MaxDateTime,
 sum(Distance) as TotalDistance
from
(
    select *
    , row_number() over (order by EventDate) - row_number() over (partition by isMainEvent order by EventDate) as rnk
    from CTE
) q
where isMainEvent = 0
group by rnk
order by rnk;

输出:

MinDateTime         MaxDateTime         TotalDistance
------------------- ------------------- -------------
2018-09-06 02:35:00 2018-09-07 23:45:00        483.00
2018-09-08 01:30:00 2018-09-09 20:00:00        143.20

答案 1 :(得分:0)

您可以尝试此解决方案。它创建仅包含主要事件的临时表,然后在循环中检查主要事件之间的距离的输入数据总和:

/*Input Table: EventLog (EventName nvarchar(max), EventDate datetime, Distance decimal(18,2))*/
DECLARE @BeginDate AS datetime
DECLARE @EndDate AS datetime
DECLARE @RowNo AS integer
--result table
DECLARE @MainEventTable table
    (RowNumber integer,
    MainEventName nvarchar(256),
    MainEventDate datetime,
    SumDistance decimal(18,2))

--Create List of Main Events
INSERT INTO @MainEventTable (RowNumber, MainEventName, MainEventDate)
    SELECT ROW_NUMBER() OVER(ORDER BY EventDate ASC), EventName, EventDate
    FROM EventLog --!! put here name of your table
    WHERE EventName IN ('Main1','Main2','Main3') --!! put here names of main events

--check number of main events
SET @RowNo = (SELECT ISNULL(MAX(RowNumber),0) FROM @MainEventTable)
SET @BeginDate = CONVERT(datetime, '9999.12.12', 102)

WHILE @RowNo > 0
    BEGIN
        SET @EndDate = @BeginDate
        SET @BeginDate = (SELECT MainEventDate FROM @MainEventTable WHERE RowNumber = @RowNo)

        UPDATE @MainEventTable 
        SET SumDistance = (
            SELECT
                SUM(Distance)
            FROM EventLog --!! put here name of your table
            WHERE EventDate >= @BeginDate AND EventDate < @EndDate)
        WHERE RowNumber = @RowNo

        SET @RowNo = @RowNo - 1
    END

SELECT * FROM @MainEventTable ORDER BY RowNumber

输入(事件日志):

EventName   EventDate               Distance
NotMain     1905-07-04 00:00:00.000 2
Main3       1905-07-05 00:00:00.000 2
Main2       1905-07-06 00:00:00.000 2
NotMain     1905-07-07 00:00:00.000 3
NotMain     1905-07-08 00:00:00.000 2
Main1       1905-07-09 00:00:00.000 1

输出:

RowNumber   MainEventName   MainEventDate           SumDistance
1           Main3           1905-07-05 00:00:00.000 2
2           Main2           1905-07-06 00:00:00.000 7
3           Main1           1905-07-09 00:00:00.000 1