I have the following MS Access DB schema:
I want to select rows from Items table ordered by Items.score so that there are at most Group.top_count rows for each group.
For example I have the following data in the tables:
Group table:
Items table:
I want to select top 2 items for group #1 and top 1 item for group #2. So the result must contain rows 1, 2 and 5.
There was a similar question at DBA stackexchange , but about SQL Server. So all answers used SQL Server syntax and I couldn't adapt it to work on MS Access.
If there were a constant number per group, you could do:
select i.*
from items as i inner join
groups as g
on i.group_id = g.id
where i.id in (select top 2 i2.id
from items i2
where i2.group_id = i.group_id
order by i2.score desc
);
Instead, you will need to enumerate the values and this is expensive in MS Access:
select i.*
from (select i.*,
(select count(*)
from items i2
where i2.group_id = i.group_id and
(i2.score < i.score or
i2.score = i.score and i2.id <= i2.id
)
) as seqnum
from items as i
) as i inner join
groups as g
on i.group_id = g.id
where i.seqnum <= g.top_count;
This logic implements the equivalent of row_number()
, which is the right way to solve this problem (if your database supports it).
Using VBA to create the SQL command, perhaps try this (untested). It basically creates a UNION that joins each grouping, and allows you to run it on any size table (not sure if there's a limit to the UNION and if it starts to bog down after many, or perhaps there's a better method where you can open a recordset/table and just write the results into that recordset/table instead of doing the UNION thing.
SET DBS = CURRENTDB
strSQL = ""
intMax = dmax("ID", "group")
FOR i = 1 TO intMax
strSQL = strSQL & "SELECT TOP " & DLOOKUP("top_count","group","ID = " & I) & " ID " & _
"FROM items WHERE group_id = " & i & " ORDER BY score "
if i < intMax
strSQL = strSQL & " UNION "
endif
next i
dbs.execute strSQL
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.