我有SQL查詢加入3個表,其中一個只是多對多連接另外兩個。我用一個Spring JDBC ResultSetExtractor類的結果集轉換成我的對象看起來大致是這樣的:如何將分頁應用於帶有聯接的SQL查詢的結果?
class Customer {
private String id;
private Set<AccountType> accountTypes;
...
}
的ResultSetExtractor類的實現看起來是這樣的:
public List<Client> extractData(ResultSet rs) throws SQLException,
DataAccessException {
Map<Integer, Client> clientsMap = new LinkedHashMap<Integer, Client>();
while (rs.next()) {
int id = rs.getInt("id");
// add the client to the map only the first time
if (!clientsMap.containsKey(id)) {
Client client = new Client();
client.setId(id);
...
clientsMap.put(id, client);
}
// always add the account type to the existing client
Client client = clientsMap.get(id);
client.addAccountType(extractAccountTypeFrom(rs, id));
}
return new ArrayList<Client>(clientsMap.values());
}
這工作得很好,而不分頁。
但是,我需要分析這些結果。我通常做的方式是通過增加這查詢,例如:
SELECT ... ORDER BY name ASC LIMIT 10 OFFSET 30;
然而,由於這一查詢聯接,當我限制結果的數量,我其實限制(連接結果的數量即作爲客戶將出現的次數與他們擁有的賬戶類型數量相同,LIMIT不是應用客戶數量,而是應用於客戶數量* accountTypes,這不是我想要的)。
我想出的唯一解決辦法是刪除該限制(和偏移,因爲這也將是錯誤的)從查詢和編程應用它們:
List<Client> allClients = jdbcTemplate.query....
List<Client> result = allClients.subList(offset, offset+limit);
但是,這顯然不是一個非常好的,高效的方案。有沒有更好的辦法?
Renato,如何在三個表上連接創建VIEW,然後使用ORDER BY名稱ASC LIMIT 10 OFFSET 30;在VIEW_NAME的select *上使用技巧?運行這個由你的DBA來看看他們是否樂意這樣做。 –
@Rob Kielty - 感謝您的建議......我會試着看看是否可能比我剛剛發佈的解決方案更有效。 – Renato
測試是要走的路。如果你有一個DBA維護數據庫,他們應該很高興你向他們詢問每種方法的優缺點。 –