Brian
Brian

Reputation: 1

SQL Server: create an incremental counter for records in the same year?

I have a table with the following columns:

EmployeeID
EventDate (mm/dd/yyyy)
Event

I need to create a new column which would count each event by year and insert a value in the format ##-yyyy. For example, I want to create a file like Counter:

EmployeeID      EventDate   Event   Counter
------------------------------------------
  001           01/05/2018    A     01-2018
  002           12/12/2018    A     01-2018
  001           03/01/2019    A     01-2019
  001           04/05/2019    A     02-2019
  002           05/05/2019    A     01-2018

I don't need to count by the event or event type. I just need to include a counter for each event in a year and to increment for each event by the date that it happened. So an event in January 2019 would have a lower number than an event in June 2019.

Upvotes: 0

Views: 2128

Answers (3)

Gustav
Gustav

Reputation: 55831

In Access, you will need a custom function like my RowNumber that allows for grouping:

' Builds consecutive row numbers in a select, append, or create query
' with the option of a initial automatic reset.
' Optionally, a grouping key can be passed to reset the row count
' for every group key.
'
' 2018-08-23. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function RowNumber( _
    ByVal Key As String, _
    Optional ByVal GroupKey As String, _
    Optional ByVal Reset As Boolean) _
    As Long

    ' Uncommon character string to assemble GroupKey and Key as a compound key.
    Const KeySeparator      As String = "¤§¤"
    ' Expected error codes to accept.
    Const CannotAddKey      As Long = 457
    Const CannotRemoveKey   As Long = 5

    Static Keys             As New Collection
    Static GroupKeys        As New Collection
    Dim Count               As Long
    Dim CompoundKey         As String

    On Error GoTo Err_RowNumber

    If Reset = True Then
        ' Erase the collection of keys and group key counts.
        Set Keys = Nothing
        Set GroupKeys = Nothing
    Else
        ' Create a compound key to uniquely identify GroupKey and its Key.
        ' Note: If GroupKey is not used, only one element will be added.
        CompoundKey = GroupKey & KeySeparator & Key
        Count = Keys(CompoundKey)

        If Count = 0 Then
            ' This record has not been enumerated.
            '
            ' Will either fail if the group key is new, leaving Count as zero,
            ' or retrieve the count of already enumerated records with this group key.
            Count = GroupKeys(GroupKey) + 1
            If Count > 0 Then
                ' The group key has been recorded.
                ' Remove it to allow it to be recreated holding the new count.
                GroupKeys.Remove (GroupKey)
            Else
                ' This record is the first having this group key.
                ' Thus, the count is 1.
                Count = 1
            End If
            ' (Re)create the group key item with the value of the count of keys.
            GroupKeys.Add Count, GroupKey
        End If
        ' Add the key and its enumeration.
        ' This will be:
        '   Using no group key: Relative to the full recordset.
        '   Using a group key:  Relative to the group key.
        ' Will fail if the key already has been created.
        Keys.Add Count, CompoundKey
    End If

    ' Return the key value as this is the row counter.
    RowNumber = Count

Exit_RowNumber:
    Exit Function

Err_RowNumber:
    Select Case Err
        Case CannotAddKey
            ' Key is present, thus cannot be added again.
            Resume Next
        Case CannotRemoveKey
            ' GroupKey is not present, thus cannot be removed.
            Resume Next
        Case Else
            ' Some other error. Ignore.
            Resume Exit_RowNumber
    End Select
End Function

Then your query could be:

SELECT 
    EmployeeID, 
    EventDate, 
    Event, 
    RowNumber(CStr([EventDate]),[EmployeeID] & "-" & CStr(Year([EventDate]))) AS RowCount, 
    Format([RowCount],"00-") & CStr(Year([EventDate])) AS EventCount
FROM 
    Events
WHERE 
    RowNumber(CStr([EventDate]),[EmployeeID] & "-" & CStr(Year([EventDate])))<>RowNumber("","",True)
ORDER BY 
    EventDate;

and the result would be:

RowNumber

Full code can be found on GitHub: VBA.RowNumbers

Upvotes: 0

Caius Jard
Caius Jard

Reputation: 74605

If this was SQL server:

SELECT
   ...,
   CONCAT(
     FORMAT(
       ROW_NUMBER() OVER(PARTITION BY employeeid, YEAR(eventdate) ORDER BY eventdate ASC), 
       'D2'
     ), 
     '-', 
     YEAR(eventdate)
   ) as counter
FROM ...

ROW_NUMBER() will increment a counter from 1, that restarts every different employee/year. We format this to have a leading 0, then append a hyphen and the year

If you want all events in the same month to have the same number, consider a DENSE_RANK() OVER(PARTITION BY employeeid, YEAR(eventdate) ORDER BY MONTH(eventdate)) instead of a row number.

Upvotes: 3

Farhad Rahmanifard
Farhad Rahmanifard

Reputation: 688

With a few differences from the answer of @Caius Jard which is almost correct.

SELECT 
    EmployeeID,
    EventDate,
    [Event],
    FORMAT(ROW_NUMBER() OVER(PARTITION BY DATEPART(YEAR, EventDate), EmployeeID, [Event] ORDER BY EventDate ASC) , 'D2') 
    + '-' 
    + FORMAT(DATEPART(YEAR, EventDate), 'D4') AS Counter
FROM YOUR_TABLE

Upvotes: 0

Related Questions