为每个组

时间:2016-09-26 10:33:45

标签: sql ms-access

我有以下MS Access数据库架构:

DB schema

我想从Items.score排序的Items表中选择行,这样每个组最多只有Group.top_count行。

例如,我在表格中有以下数据:

组表:

Group table

项目表:

Items table

我想为组#1选择前2项,为组#2选择前1项。因此结果必须包含第1,2和5行。

有一个similar question at DBA stackexchange,但关于SQL Server。因此,所有答案都使用SQL Server语法,我无法使其适应MS Access。

2 个答案:

答案 0 :(得分:2)

如果每组有一个常数,你可以这样做:

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
              );

相反,您需要枚举值,这在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;

此逻辑实现了row_number()的等价物,这是解决此问题的正确方法(如果您的数据库支持它)。

答案 1 :(得分:0)

使用VBA创建SQL命令,也许尝试这个(未经测试)。它基本上创建了一个连接每个分组的UNION,并允许你在任何大小的表上运行它(不确定UNION是否存在限制,以及它是否会在很多之后开始陷入困境,或者可能会出现这种情况。更好的方法,你可以打开一个记录集/表,只是将结果写入该记录集/表而不是做UNION的事情。

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