3

I Have an SQL query giving me X results, I want the query output to have a coulmn called count making the query somthing like this:

count id section
1     15    7
2     3     2
3     54    1
4     7     4

How can I make this happen?

fingerman
  • 2,440
  • 4
  • 19
  • 24
  • 1
    Why would you want to do this? If your reading a list of records you can increment a varaible in your code. – Geoffrey Jun 09 '11 at 14:28
  • I'm using access forms for a school project, I'm actually doing it so I can later catch the third record or fifth record stright away... Anyway, I'm willing to use VBA but i Would much rather use pure SQL – fingerman Jun 09 '11 at 14:32
  • Then just use a limit clause: SELECT * FROM table WHERE a = b LIMIT 5,1 – Geoffrey Jun 09 '11 at 14:37
  • ms-access doesn't have a limit keyword.... – fingerman Jun 09 '11 at 14:40
  • I beleive it is "SELECT TOP 1 * FROM table WHERE a = b" – Geoffrey Jun 09 '11 at 14:44
  • yha, but thats only top.. not third record... – fingerman Jun 09 '11 at 14:49
  • Sorry, access is not my strong point, but from what I can tell it is not possible with it, see: http://www.pcreview.co.uk/forums/query-return-record-nth-physical-location-table-t2776701.html – Geoffrey Jun 09 '11 at 14:53
  • Yha, but that's about a table. a query is sorted. at least mine is. – fingerman Jun 09 '11 at 14:56
  • Not the point, it is techincally incorrect to pick the Nth record from a query set in pure SQL and as such access does not support it at all. – Geoffrey Jun 09 '11 at 14:59
  • I don't remember Access very well (been years since I use it), but as it doesn't support in-line "derived tables", my understanding is you need to have two queries, with one referencing the other one. In the first (inner) one, select TOP 5 in Ascending order, and in the second select TOP 1 in Descending. Not sure you can specify the "TOP N" parameter dynamically though, so you might need to go with VBA – Tao Jun 09 '11 at 14:59
  • @gnif but it is correct, because say I have a birthday table, with people names and birthdays, my query sorts this table by alphabaticaly by name - I can pick the one with the "highest name", I should be able to pick the one with the third 'heighst' name... so I should be able to have a coulmn specifing the n'th place of the entry – fingerman Jun 09 '11 at 15:04
  • @TAO care to give a working example? – fingerman Jun 09 '11 at 15:04
  • Just tested, and confirmed: You can't specify the TOP parameter dynamically in a saved query. So, for a static Nth record it's two queries (eg `SELECT TOP 5 * FROM Table1 ORDER BY DataField;` and `SELECT TOP 1 * FROM Query1 ORDER BY DataField DESC;`), and for a dynamic one you'd need to use VBA: prep a query like the first one, and skip to the last record. – Tao Jun 09 '11 at 15:13
  • Actually, there's a pair of reasonably cute solutions here: http://www.techrepublic.com/blog/msoffice/an-access-query-that-returns-every-nth-record/3617 – Tao Jun 09 '11 at 15:19
  • The N in TOP N is not parameterizable in Access/Jet/ACE SQL. – David-W-Fenton Jun 12 '11 at 22:15
  • 1
    @Tao: when you say Access doesn't support `in-line "derived tables"` what do you mean? Jet/ACE SQL certainly supports what I refer to as derived tables (subqueries in the FROM clause), and it always has. The default syntax is a little odd, but it works. Indeed, in current versions of Access if you type in standard SQL syntax for this, the Access QBE will convert it to its own dialect for you. – David-W-Fenton Jun 12 '11 at 22:16
  • @David-W-Fenton: Thanks for the correction, you're absolutely right, it works perfectly and I have no idea why I thought there was this limitation! In conclusion, you CAN in fact create a single query that selects the 5th record (for example) with something like `SELECT TOP 1 * FROM (SELECT TOP 5 * FROM Table1 ORDER BY DataField) AS Test1 ORDER BY DataField DESC;`, and you can parameterize it by constructing it dynamically from within VBA. – Tao Jun 13 '11 at 07:23

7 Answers7

3

The only trick I have seen is if you have a sequential id field, you can create a new field in which the value for each record is 1. Then you do a running sum of that field.

Add to your query

DSum("[New field with 1 in it]","[Table Name]","[ID field]<=" & [ID Field]) 
as counterthing

That should produce a sequential count in Access which is what I think you want.

HTH.

(Stolen from Rob Mills here: http://www.access-programmers.co.uk/forums/showthread.php?p=160386)

dazed-and-confused
  • 1,293
  • 2
  • 11
  • 19
mikeY
  • 519
  • 4
  • 14
2

So in your example, "count" is the derived sequence number? I don't see what pattern is used to determine the count must be 1 for id=15 and 2 for id=3.

count id section
1     15    7
2     3     2
3     54    1
4     7     4

If id contained unique values, and you order by id you could have this:

count id section
1     3     2
2     7     4
3     15    7
4     54    1

Looks to me like mikeY's DSum approach could work. Or you could use a different approach to a ranking query as Allen Browne described at this page

Edit: You could use DCount instead of DSum. I don't know how the speed would compare between the two, but DCount avoids creating a field in the table simply to store a 1 for each row.

DCount("*","YourTableName","id<=" & [id]) AS counter

Whether you go with DCount or DSum, the counter values can include duplicates if the id values are not unique. If id is a primary key, no worries.

HansUp
  • 95,961
  • 11
  • 77
  • 135
2

I frankly don't understand what it is you want, but if all you want is a sequence number displayed on your form, you can use a control bound to the form's CurrentRecord property. A control with the ControlSource =CurrentRecord will have an always-accurate "record number" that is in sequence, and that will update when the form's Recordsource changes (which may or may not be desirable).

You can then use that number to navigate around the form, if you like.

But this may not be anything like what you're looking for -- I simply can't tell from the question you've posted and the "clarifications" in comments.

David-W-Fenton
  • 22,871
  • 4
  • 45
  • 58
  • +1 While I can't claim to fully understand your answer, I think in essence it means, "more suited to the front end" :) P.S. I shall resist the temptation to suggest using the MSDataShape provider `APPEND` an empty column that can be populated in front-end code ;) – onedaywhen Jun 13 '11 at 10:42
  • A "record number" has meaning only in a front-end environment, no? That is, a sequence has no meaning except in a particular dataset. In this case, the description of the problem was a front-end issue (though this was not clear from the question, but only came out in the comments to the question), so a front-end solution seems entirely appropriate. – David-W-Fenton Jun 15 '11 at 21:33
  • it is indeed true that a relation has no ordering by definition. Whether for Access (ACE, Jet, whatever) the contents of a base table (which has a predictable physical ordering on disk) or the result of a SELECT query with an INTO clause (I don't know what this is called: it is not a 'table' so I go with resultset) can be a relation I leave up to you... – onedaywhen Jun 16 '11 at 09:21
  • ...However, a table can have a `record number` (or `start_date` etc) attribute and the database schema provides the DBMS-understood meaning of the data which can imply ordering. Put another way, semantics aren't the preserve of the front end application. – onedaywhen Jun 16 '11 at 09:29
1

Alright, I guess this comes close enough to constitute an answer: the following link specifies two approaches: http://www.techrepublic.com/blog/microsoft-office/an-access-query-that-returns-every-nth-record/

The first approach assumes that you have an ID value and uses DCount (similar to @mikeY's solution).

The second approach assumes you're OK creating a VBA function that will run once for EACH record in the recordset, and will need to be manually reset (with some VBA) every time you want to run the count - because it uses a "static" value to run its counter.

As long as you have reasonable numbers (hundreds, not thousands) or records, the second approach looks like the easiest/most powerful to me.

Tao
  • 13,457
  • 7
  • 65
  • 76
  • I ended up using your solution from the comments... Which does mean I have to create a a few queries but that is acceptable – fingerman Jun 09 '11 at 17:33
0

This function can be called from each record if available from a module.

Example: incrementingCounterTimeFlaged(10,[anyField]) should provide your query rows an int incrementing from 0.

'provides incrementing int values 0 to n
'resets to 0 some seconds after first call
Function incrementingCounterTimeFlaged(resetAfterSeconds As Integer,anyfield as variant) As Integer

Static resetAt As Date
Static i As Integer
'if reset date < now() set the flag and return 0

If DateDiff("s", resetAt, Now()) > 0 Then
    resetAt = DateAdd("s", resetAfterSeconds, Now())
    i = 0
    incrementingCounterTimeFlaged = i
'if reset date > now increments and returns
Else
    i = i + 1
    incrementingCounterTimeFlaged = i
End If    
End Function
user6788933
  • 285
  • 2
  • 10
0

autoincrement in SQL

SELECT (Select COUNT(*) FROM table A where A.id<=b.id),B.id,B.Section FROM table AS B ORDER BY B.ID Asc
-1

You can use ROW_NUMBER() which is in SQL Server 2008

SELECT ROW_NUMBER() OVER (ORDER By ID DESC) RowNum,
    ID,
    Section
FROM myTable

Then RowNum displays sequence of row numbers.

Maxali
  • 1,934
  • 2
  • 16
  • 25