1

What I am trying to do is fairly simple. I just want to add a row number to a query. Since this is in Access is a bit more difficult than other SQL, but under normal circumstances is still doable using solutions such as DCount or Select Count(*), example here: How to show row number in Access query like ROW_NUMBER in SQL or Access SQL how to make an increment in SELECT query

My Issue

My issue is I'm trying to add this counter to a multi-join query that orders by fields from numerous tables.

Troubleshooting

My code is a bit ridiculous (19 fields, seven of which are long expressions, from 9 different joined tables, and ordered by fields from 5 of those tables). To make things simple, I have an simplified example query below:

Example Query

SELECT DCount("*","Requests_T","[Requests_T].[RequestID]<=" & [Requests_T].[RequestID]) AS counter, Requests_T.RequestHardDeadline AS Deadline, Requests_T.RequestOverridePriority AS Priority, Requests_T.RequestUserGroup AS [User Group], Requests_T.RequestNbrUsers AS [Nbr of Users], Requests_T.RequestSubmissionDate AS [Submitted on], Requests_T.RequestID
FROM (((((((Requests_T 
    INNER JOIN ENUM_UserGroups_T ON ENUM_UserGroups_T.UserGroups = Requests_T.RequestUserGroup) 
    INNER JOIN ENUM_RequestNbrUsers_T ON ENUM_RequestNbrUsers_T.NbrUsers = Requests_T.RequestNbrUsers) 
    INNER JOIN ENUM_RequestPriority_T ON ENUM_RequestPriority_T.Priority = Requests_T.RequestOverridePriority) 
ORDER BY Requests_T.RequestHardDeadline, ENUM_RequestPriority_T.DisplayOrder DESC , ENUM_UserGroups_T.DisplayOrder, ENUM_RequestNbrUsers_T.DisplayOrder DESC , Requests_T.RequestSubmissionDate;

If the code above is trying to select a field from a table not included, I apologize - just trust the field comes from somewhere (lol i.e. one of the other joins I excluded to simply the query). A great example of this is the .DisplayOrder fields used in the ORDER BY expression. These are fields from a table that simply determines the "priority" of an enum. Example: Requests_T.RequestOverridePriority displays to the user as an combobox option of "Low", "Med", "High". So in a table, I assign a numerical priority to these of "1", "2", and "3" to these options, respectively. Thus when ENUM_RequestPriority_T.DisplayOrder DESC is called in order by, all "High" priority requests will display above "Medium" and "Low". Same holds true for ENUM_UserGroups_T.DisplayOrder and ENUM_RequestNbrUsers_T.DisplayOrder.

I'd also prefer to NOT use DCOUNT due to efficiency, and rather do something like:

select count(*) from Requests_T where Requests_T.RequestID>=RequestID) as counter

Due to the "Order By" expression however, my 'counter' doesn't actually count my resulting rows sequentially since both of my examples are tied to the RequestID.

Example Results

Based on my actual query results, I've made an example result of the query above.

Counter  Deadline   Priority  User_Group  Nbr_of_Users  Submitted_on  RequestID
5        12/01/2016 High      IT          2-4           01/01/2016    5
7        01/01/2017 Low       IT          2-4           05/06/2016    8
10                  Med       IT          2-4           07/13/2016    11
15                  Low       IT          10+           01/01/2016    16
8                   Low       IT          2-4           01/01/2016    9
2                   Low       IT          2-4           05/05/2016    2

The query is displaying my results in the proper order (those with the nearest deadline at the top, then those with the highest priority, then user group, then # of users, and finally, if all else is equal, it is sorted by submission date). However, my "Counter" values are completely wrong! The counter field should simply intriment +1 for each new row. Thus if displaying a single request on a form for a user, I could say

"You are number: Counter [associated to RequestID] in the development queue."

Meanwhile my results:

  1. Aren't sequential (notice the first four display sequentially, but then the final two rows don't)! Even though the final two rows are lower in priority than the records above them, they ended up with a lower Counter value simply because they had the lower RequestID.
  2. They don't start at "1" and increment +1 for each new record.

Ideal Results

Thus my ideal result from above would be:

Counter  Deadline   Priority  User_Group  Nbr_of_Users  Submitted_on  RequestID
1        12/01/2016 High      IT          2-4           01/01/2016    5
2        01/01/2017 Low       IT          2-4           05/06/2016    8
3                   Med       IT          2-4           07/13/2016    11
4                   Low       IT          10+           01/01/2016    16
5                   Low       IT          2-4           01/01/2016    9
6                   Low       IT          2-4           05/05/2016    2

I'm spoiled by PLSQL and other software where this would be automatic lol. This is driving me crazy! Any help would be greatly appreciated.

FYI - I'd prefer an SQL option over VBA if possible. VBA is very much welcomed and will definitely get an up vote and my huge thanks if it works, but I'd like to mark an SQL option as the answer.

Community
  • 1
  • 1
TMY
  • 471
  • 1
  • 7
  • 20
  • Your counter will be very difficult as it must correlate to every field in your `ORDER BY` clause and these come from joins. Hence, your count subquery will have to have joins. Even more challenging is the swap between *ASC* and *DESC*. – Parfait Oct 12 '16 at 17:55
  • 1
    Alternatively, append query records to temp table with autonumber and then run count subquery (since auto increment ID can skip around due to data changes). This way, your correlation is just one table with no joins but still the swap becomes an issue. – Parfait Oct 12 '16 at 17:56

1 Answers1

0

Unfortuantely, MS Access doesn't have the very useful ROW_NUMBER() function like other clients do. So we are left to improvise.

Because your query is so complicated and MS Access does not support common table expressions, I recommend you follow a two step process. First, name that query you already wrote IntermediateQuery. Then, write a second query called FinalQuery that does the following:

SELECT i1.field_primarykey, i1.field2, ... , i1.field_x,
    (SELECT field_primarykey FROM IntermediateQuery i2
     WHERE t2.field_primarykey <= t1.field_primarykey) AS Counter
FROM IntermediateQuery i1
ORDER BY Counter

The unfortunate side effect of this is the more data your table returns, the longer it will take for the inline subquery to calculate. However, this is the only way you'll get your row numbers. It does depend on having a primary key in the table. In this particular case, it doesn't have to be an explicitly defined primary key, it just needs to be a field or combination of fields that is completely unique for each record.

SandPiper
  • 2,816
  • 5
  • 30
  • 52