John said:
A monstrous SQL query might be possible, but I'm guessing that VBA
code would be much better. You could open a Recordset based on the
table and step through it with MoveNext, accumulating counts of 0's
and -1's.
John, Glad to hear you have got the message that saying a Jet table is
an 'unordered bucket of data' is not true <g>; if it were, your
solution would be unworkable.
The fact that a table with no PRIMARY KEY designation is physically
stored in (relative) date/time entered order and that in absence of an
explicit ORDER BY clause the data will retain this order can be further
exploited, along with some other 'features' of Jet...
Consider this as being the OP's base table:
CREATE TABLE Test (
data_col INTEGER DEFAULT 0 NOT NULL,
CHECK (data_col IN (0, -1))
)
;
INSERT INTO Test VALUES (0)
;
INSERT INTO Test VALUES (0)
;
INSERT INTO Test VALUES (0)
;
INSERT INTO Test VALUES (-1)
;
INSERT INTO Test VALUES (-1)
;
INSERT INTO Test VALUES (0)
;
INSERT INTO Test VALUES (-1)
;
INSERT INTO Test VALUES (-1)
;
INSERT INTO Test VALUES (-1)
;
INSERT INTO Test VALUES (0)
;
INSERT INTO Test VALUES (-1)
;
INSERT INTO Test VALUES (-1)
;
INSERT INTO Test VALUES (0)
;
INSERT INTO Test VALUES (0)
;
Now create a working table which will apply a row ID to the original
data in date/time entered order by exploiting the non-relational
autonumber (a.k.a. IDENTITY) feature:
CREATE TABLE WorkingTable (
row_ID INTEGER IDENTITY(1, 1) NOT NULL,
data_col INTEGER DEFAULT 0 NOT NULL,
CHECK (data_col IN (0, -1))
)
;
INSERT INTO WorkingTable (data_col)
SELECT data_col FROM Test
;
With the row_ID, I trust you can see how this task is a whole lot
easier. Here's one way of detecting on which row the data sequence
changes:
SELECT W1.row_ID, W1.data_col,
(SELECT MAX(W2.row_ID)
FROM WorkingTable AS W2
WHERE W1.row_ID > W2.row_ID AND W1.data_col <> W2.data_col) AS change
FROM WorkingTable AS W1
;
Put this in a Query object (a.k.a. VIEW) to make subsequent querying
easier:
CREATE VIEW WorkingView
AS
SELECT DISTINCT IIF(DT1.change IS NULL, 0, DT1.change) AS row_ID,
DT1.data_col
FROM (
SELECT W1.row_ID, W1.data_col,
(SELECT MAX(W2.row_ID)
FROM WorkingTable AS W2
WHERE W1.row_ID > W2.row_ID AND W1.data_col <> W2.data_col) AS change
FROM WorkingTable AS W1
) AS DT1
;
Then we can exploit another 'feature' of Jet i.e. 'calculating
correlation names':
SELECT v1.data_col,
v1.row_id AS start_row, (
SELECT MIN(v2.row_id)
FROM WorkingView AS V2
WHERE v2.row_id > v1.row_id
) AS end_row,
end_row - start_row AS count_of
FROM WorkingView AS V1
ORDER BY v1.data_col, v1.row_id
;
A special case is required to handle the final value but you get the
idea. I'm sure there's a short cut I'm not seeing (is my SQL
monstrous?) but my coffee is already cold ;-)