sql >> データベース >  >> RDS >> Sqlserver

フィールドの状態変化の開始時刻と終了時刻を取得する

    SQL Server 2012 以降を使用している場合は、SQL Server のウィンドウ関数を使用して、次のように目的の結果を得ることができます:

    CREATE TABLE [dbo].[EventStates](
        [Item] [varchar](1) NOT NULL,
        [EventDate] [varchar](19) NOT NULL,
        [Event] [varchar](3) NOT NULL
    ) ON [PRIMARY]
    
    GO
    
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'A', N'2011-10-03 00:01:00', N'On')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'A', N'2011-10-03 00:01:15', N'On')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'B', N'2011-10-03 00:01:00', N'On')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'A', N'2011-10-03 00:02:00', N'Off')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'A', N'2011-10-03 00:02:01', N'Off')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'C', N'2011-10-03 00:01:00', N'On')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'B', N'2011-10-03 00:02:00', N'Off')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'A', N'2011-10-03 00:02:02', N'On')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'C', N'2011-10-03 00:02:05', N'On')
    INSERT [dbo].[EventStates] ([Item], [EventDate], [Event]) VALUES (N'A', N'2011-10-03 00:02:07', N'Off')
    
    GO
    
    ;WITH StateChange
    AS
    (
        SELECT   E.[Item]
                ,E.[EventDate]
                ,E.[Event]
                ,(  -- First determine if a state change to on has occurred.
                    CASE
                        WHEN E.[Event] = 'On' AND LAG(E.[Event], 1, NULL) OVER (PARTITION BY E.[Item] ORDER BY E.[EventDate] ASC) IS NULL THEN 1
                        WHEN E.[Event] = 'On' AND E.[Event] <> LAG(E.[Event], 1, NULL) OVER (PARTITION BY E.[Item] ORDER BY E.[EventDate] ASC) THEN 1
                        ELSE 0
                    END
                 ) [StateChanged]
        FROM    EventStates E
    ), StateChangeGrouping
    AS
    (
        SELECT   [Item]
                ,[EventDate]
                ,[Event]
                ,[StateChanged]
                ,SUM([StateChanged]) OVER (PARTITION BY [Item] ORDER BY [EventDate] ASC) AS [GroupID]
        FROM    StateChange 
    ), StateChangeRanked
    AS
    (
        SELECT   [Item]
                ,[EventDate]
                ,[Event]
                ,[StateChanged]
                ,[GroupID]
                ,ROW_NUMBER() OVER (PARTITION BY [Item], GroupID, [Event] ORDER BY [EventDate]) AS TransitionRank
        FROM    StateChangeGrouping
    )
    SELECT      [Item]
                ,MIN([EventDate]) AS [Start]
                ,MAX([EventDate]) AS [End]
                ,[GroupID]
    FROM        StateChangeRanked
    WHERE       GroupID > 0 AND TransitionRank = 1
    GROUP BY    [Item], GroupID
    ORDER BY    [Item], [Start]
    

    以下は、SQL Server 2008 の実装です。

    ;WITH EventID
    AS
    (
        SELECT   ROW_NUMBER() OVER(PARTITION BY [Item] ORDER BY [EventDate]) RowNr
                ,[Item]
                ,[EventDate]
                ,[Event] 
        FROM    [dbo].[EventStates]
    ), StateChange
    AS
    (
        SELECT  C.RowNr
                ,P.RowNr AS P_RowNr
                ,C.[Item]
                ,C.[EventDate]
                ,C.[Event] 
                ,P.[Event] AS P_Event
                ,(  -- First determine if a state change to on has occurred.
                    CASE
                        WHEN C.[Event] = 'On' AND P.[Event] IS NULL THEN 1
                        WHEN C.[Event] = 'On' AND C.[Event] <> P.[Event] THEN 1
                        ELSE 0
                    END
                    ) [StateChanged]
        FROM    EventID C
        LEFT OUTER JOIN EventID P ON C.Item = P.Item AND C.RowNr = P.RowNr + 1
    ), StateChangeGrouping
    AS
    (
        SELECT   ST1.[Item]
                ,ST1.[EventDate]
                ,ST1.[Event]
                ,ST1.[StateChanged]
                ,(
                    SELECT SUM([StateChanged])
                    FROM StateChange ST2
                    WHERE ST2.Item = ST1.Item AND ST2.RowNr <= ST1.RowNr
                 ) AS GroupID
        FROM    StateChange ST1
    ), StateChangeRanked
    AS
    (
        SELECT   [Item]
                ,[EventDate]
                ,[Event]
                ,[StateChanged]
                ,[GroupID]
                ,ROW_NUMBER() OVER (PARTITION BY [Item], GroupID, [Event] ORDER BY [EventDate]) AS TransitionRank
        FROM    StateChangeGrouping
    )
    SELECT      [Item]
                ,MIN([EventDate]) AS [Start]
                ,MAX([EventDate]) AS [End]
                ,[GroupID]
    FROM        StateChangeRanked
    WHERE       GroupID > 0 AND TransitionRank = 1
    GROUP BY    [Item], GroupID
    ORDER BY    [Item], [Start]
    



    1. MySQL GROUPBY2列

    2. M、Dはdecimal(M、D)で正確に何を意味しますか?

    3. 指定された名前と引数のタイプに一致する演算子はありません。明示的な型キャストを追加する必要があるかもしれません。 --Netbeans、Postgresql 8.4、Glassfish

    4. 単一のDjangoアプリと同じサーバーでクライアントを作成する際の自動移行を使用して、クライアントごとにPostgreSQLデータベースを分離します