sql server: peak active users by date range

ycggw6v2  于 2023-04-10  发布在  SQL Server
关注(0)|答案(2)|浏览(138)

I needs to get count of max active users by date range. Acrive users - it is a maximum number of not removed users. I have UsersHistory Table:
| HistoryID | UserID | IsRemoved | OperationID | ModificationDate |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| 1 | 1 | 0 | 'Add' | 2012-07-24 04:27:48 |
| 2 | 2 | 0 | 'Add' | 2012-07-26 04:18:48 |
| 3 | 3 | 0 | 'Add' | 2012-07-27 04:29:48 |
| 4 | 1 | 0 | 'Update' | 2012-07-28 04:47:48 |
| 5 | 2 | 0 | 'Update' | 2012-07-29 04:01:48 |
| 6 | 1 | 1 | 'Remove' | 2012-08-28 04:34:48 |
| 7 | 2 | 1 | 'Remove' | 2012-08-28 04:18:48 |
| 8 | 3 | 1 | 'Remove' | 2012-08-28 04:29:48 |
| 9 | 4 | 0 | 'Add' | 2012-09-24 04:27:48 |
| 10 | 5 | 0 | 'Add' | 2012-09-26 04:18:48 |
| 11 | 6 | 0 | 'Add' | 2012-09-27 04:29:48 |
| 12 | 7 | 0 | 'Add' | 2012-09-27 04:29:48 |

Expected result: Max active users by this period: 4 (HistoryID: 9, 10, 11, 12)

Update1:

HistoryID    UserID     IsRemoved       OperationID   ModificationDate
----------------------------------------------------------------------
1            1             0             'Add'      2012-07-24 04:27:48
2            2             0             'Add'      2012-07-26 04:18:48
3            3             0             'Add'      2012-07-27 04:29:48
4            1             1             'Remove'   2012-07-28 04:47:48
5            2             1             'Remove'   2012-07-28 04:47:48
6            3             1             'Remove'   2012-07-28 04:47:48

Expected result: Maximum of active(not removed) users by this period: 3

cgh8pdjw

cgh8pdjw1#

This should work for you. It will count total number of operations Add and total operations of Remove . After It subract total count of Remove from total count of Add .

DECLARE @counter1 INT,
        @counter2 INT,
        @result   INT

SELECT @counter1 = c1 
FROM(
    SELECT COUNT(HistoryID) AS c1
    FROM   UsersHistory
    WHERE  OperationId = 'Add' 
    ) x
SELECT @counter2 = c2 
FROM(
    SELECT COUNT(HistoryID) AS c2
    FROM   UsersHistory
    WHERE  OperationId = 'Remove'
    ) a

SET    @result = @counter1 - @counter2
SELECT @result

EDIT

Here you go (It should count maximum as you need):

SELECT TOP 1 COUNT(*) AS maxRes
FROM (
    SELECT DENSE_RANK() OVER (ORDER BY UserID ASC) AS [MaximumCount], *
    FROM UsersHistory
    WHERE OperationId = 'Add'
    ) a 
WHERE  
[MaximumCount] = UserID 
GROUP BY MaximumCount
ORDER BY maxRes DESC
mnowg1ta

mnowg1ta2#

If I understand you correctly you need to make islands by OperationID and count maximum count of rows in 'Add' islands. If so then:

DECLARE @History TABLE
    (
      HistoryID INT ,
      UserID INT ,
      IsRemoved BIT ,
      OperationID NVARCHAR(20)
    )

INSERT  INTO @History
VALUES  ( 1, 1, 0, 'Add' ),
        ( 2, 2, 0, 'Add' ),
        ( 3, 3, 0, 'Add' ),
        ( 4, 1, 1, 'Remove' ),
        ( 5, 2, 1, 'Remove' ),
        ( 6, 3, 1, 'Remove' ),
        ( 7, 3, 0, 'Add' );
WITH    cte1
          AS ( SELECT   OperationID ,
                        ROW_NUMBER() OVER ( ORDER BY HistoryID ) AS ID ,
                        1 AS Dummy ,
                        IIF(ISNULL(LAG(OperationID) OVER ( ORDER BY HistoryID ),
                                   OperationID) = OperationID, 0, 1) AS ChangeMark
               FROM     @History
             ),
        cte2
          AS ( SELECT   * ,
                        SUM(Dummy) OVER ( ORDER BY ID )
                        + SUM(ChangeMark) OVER ( ORDER BY ID ) AS InervalID
               FROM     cte1
             ),
        cte3
          AS ( SELECT   StartSeqNo = MIN(InervalID) ,
                        EndSeqNo = MAX(InervalID)
               FROM     ( SELECT    InervalID ,
                                    rn = InervalID
                                    - ROW_NUMBER() OVER ( ORDER BY InervalID )
                          FROM      cte2
                        ) a
               GROUP BY rn
             ),
        cte4
          AS ( SELECT   COUNT(*) AS C
               FROM     cte2 c2
                        JOIN cte3 c3 ON c2.InervalID BETWEEN c3.StartSeqNo AND     c3.EndSeqNo
               WHERE    c2.OperationID = 'Add'
               GROUP BY c3.EndSeqNo
             )
    SELECT  MAX(c) AS UserCount
    FROM    cte4

相关问题