ms-access

Access Formula to Auto-Number Rows by 4's


I have seen variations of my question answered here:

But none of them show how to calculate row numbers in groups of X number (e.g. 4's), which should have no relation to anything in the data itself. So what formula can be entered that will result in this:

ID Name Grade Crate
123456 Joe Smith 5 1
789123 Tina Turner 3 1
111225 Jamie Alot 12 1
888556 Bella Cona 10 1
158998 Melanie P 10 2
859985 Jackie Lee 8 2
789888 Tommy Pine 6 2
159874 Leroy Badoy 2 2
889777 Pana Wama 6 3
789541 Lambda Sam 12 3
789541 Pam Badame 8 3
789541 Simba Limba 4 3

Notice specifically how the Crate Number increments UP by 1 every 4 rows? It matters NOT the sort of the rows. Use Case: I need to distribute computer equipment that fits in boxes that only fits four devices per box, so I need to identify what crate each device should go in for delivery.

I've tried the VB Script and downloaded the sample Access Files and tried modifying the following column formulas in Access queries but haven't found the combo I need:

(select count(*) from yourtable t2 
 where t2.Group1 = t.Group1
   and (t2.Value < t.Value
        or (t2.Value = t.Value and t2.ID <= t.ID)) ) as Rownum

(Select Count(*) 
        From YourTable As T 
        Where T.ID < YourTable.Id) Mod 11 + 1

I'm not understanding what the formula do I supposed to even make it do what I need in my situation. Anyone have the answer at the top of mind?


Solution

  • To get the desired "Crate" value, you need assign table rows with unique numbers (rn).
    Then Crate=(rn/4)+1 (integer divide). In Access VBA Crate=(rn\4)+1.

    Usually, a function like "row_number()over(...)" is used for this.
    MS Access does not support such a function and the calculation is performed using formulas similar to the ones you provided.
    However, this formula implements another standard SQL function, "rank()over(...)".
    There is no difference between them ("row_number()" and "rank()") if the table rows are unique within the columns being counted. See example in fiddle

    Let's look at the calculation formula you provided using your data as an example. I added one line to the example to better show the calculation features.

        ('789541', 'Simba Limba', '4', '3') -- existing row  
        ('789541', 'Simba Limba', '5', '3') -- new row added to sample
    

    1.First case

      (Select Count(*) From tableName As T2 Where T2.ID < T.ID)+1 formulaNum1
    

    Because Id is not unique, all rows with Id=789541 take num=6.

    2.Next case

    (Select Count(*) From tableName As T2 
            Where (T2.ID < T.ID) 
                or(T2.ID = T.ID and T2.Name<t.Name)
       )+1 formulaNum2
    

    For columns(ID,Name) values (789541,Simba Limba) is not unique, all rows with Id=789541,Name=Simba Limba take num=8.

    3.Last case

    (Select Count(*) From tableName As T2 
            Where (T2.ID < T.ID) 
                or(T2.ID = T.ID and T2.Name<t.Name)
                or(T2.ID = T.ID and T2.Name=t.Name and T2.Grade<t.Grade)
       )+1 formulaNum3
    

    All rows have unique values for columns set (ID,Name,Grade) 4. Finally, calculate newCrate

      ,((Select Count(*) From tableName As T2 
            Where (T2.ID < T.ID) 
                or(T2.ID = T.ID and T2.Name<t.Name)
                or(T2.ID = T.ID and T2.Name=t.Name and T2.Grade<t.Grade)
       )+0)/4+1 newCratefrom tableName t
    

    (change "/" to "\" in VBA)

    Query

    select * 
      ,(Select Count(*) From tableName As T2 
            Where T2.ID < T.ID)+1 formulaNum1
      ,(Select Count(*) From tableName As T2 
            Where (T2.ID < T.ID) 
                or(T2.ID = T.ID and T2.Name<t.Name)
       )+1 formulaNum2
      ,(Select Count(*) From tableName As T2 
            Where (T2.ID < T.ID) 
                or(T2.ID = T.ID and T2.Name<t.Name)
                or(T2.ID = T.ID and T2.Name=t.Name and T2.Grade<t.Grade)
       )+1 formulaNum3
      ,((Select Count(*) From tableName As T2 
            Where (T2.ID < T.ID) 
                or(T2.ID = T.ID and T2.Name<t.Name)
                or(T2.ID = T.ID and T2.Name=t.Name and T2.Grade<t.Grade)
       )+0)/4+1 newCratefrom tableName t
    order by id,Name,Grade;
    
    ID Name Grade Crate formulaNum1 formulaNum2 formulaNum3 newCrate
    111225 Jamie Alot 12 1 1 1 1 1
    123456 Joe Smith 5 1 2 2 2 1
    158998 Melanie P 10 2 3 3 3 1
    159874 Leroy Badoy 2 2 4 4 4 1
    789123 Tina Turner 3 1 5 5 5 2
    789541 Lambda Sam 12 3 6 6 6 2
    789541 Pam Badame 8 3 6 7 7 2
    789541 Simba Limba 4 3 6 8 8 2
    789541 Simba Limba 5 3 6 8 9 3
    789888 Tommy Pine 6 2 10 10 10 3
    859985 Jackie Lee 8 2 11 11 11 3
    888556 Bella Cona 10 1 12 12 12 3
    889777 Pana Wama 6 3 13 13 13 4

    fiddle

    Part 2
    Another simple way to set row numbers is using public function with static variable like

    Option Compare Database
    Option Explicit
    
    Public Function GetSeqNum(Optional NewValue As Variant) As Long
    Static currentSeq As Long
        If Not IsNull(NewValue) Then
            currentSeq = currentSeq + 1
        Else
            currentSeq = 0
        End If
        GetSeqNum = currentSeq
    End Function
    

    This function defined in module.

    Use this function as

    SELECT T.*,(GetSeqNum(Id)\4+1) as Crate
    FROM yourTable as T
    

    To reset sequence, call

      GetSeqNum(null)
    

    from VBA.