【问题标题】:SUM() Several dateperiods in same datasetSUM() 同一数据集中的几个日期周期
【发布时间】:2019-02-27 18:52:18
【问题描述】:

我需要一些关于如何解决报告查询问题的想法。
正在使用 3 列,都在同一个表中,“EventDate”、“Distance”和“EventName”。 对于每个注册的事件,事件的时间和日期与“事件名称”一起记录。
我需要查询做的是计算所谓的主要事件之间的 SUM(距离),主要事件有设定的名称,但每天可以重复发生几次。

我想不出一种方法来编写一个使用“EventDate”的查询,其中“EventName” = 'something' 然后继续运行直到到达“EventName” = 'Something else' 然后给出 SUM(Distance) 然后重新开始从下一个“EventName”='something' 开始,并一直这样做,直到数据集中没有更多具有“EventName”='something' 的记录。

抱歉,如果这令人困惑,非常感谢任何帮助或代码 sn-p 让我继续解决这个问题。

    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”。

【问题讨论】:

  • 您能否添加一些示例数据以及您希望从查询中获得的预期结果?
  • 谢谢,添加了一些示例数据来说明。

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


【解决方案1】:

这听起来像是一个孤岛问题。

您可以根据事件类型生成排名。
然后按该排名分组并计算与该排名的总距离。

示例 sn-p:

-- 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

【讨论】:

  • 您好,感谢您的帮助。我现在得到了除 isMainEvent 之外的所有事件的总和。我从您的示例中看到您设法将 isMaintEvent 也包含在您的总和中,您是如何做到的?
  • @Tommel 如果您查看 CTE 中的第一个查询,IIF 只是使用了一个简单的规则。如果您通过不在外部查询中分组来修改 SQL,而只执行 select *,那么您将看到计算出的 rnk 如何标记组。
【解决方案2】:

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

/*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

【讨论】:

    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    相关资源
    最近更新 更多