2016-09-26 129 views
0

我有以下的MS Access數據庫架構:爲每個組選擇前N行

DB schema

我想選擇由Items.score訂購的商品表中的行,這樣最多有Group.top_count每組的行數。

例如,我有表中的以下數據:

組表:

Group table

項目表:

Items table

我要選擇頂部2項對於組#1和組#1的前1個項目。所以結果必須包含行1,2和5.

有一個similar question at DBA stackexchange,但關於SQL Server。所以所有的答案都使用了SQL Server語法,我無法使它適應MS Access。

回答

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(),這是解決此問題的正確方法(如果數據庫支持它)。

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