如何使用Joins将分页应用于SQL查询的结果?

我有SQL查询连接3个表,一个只是多对多连接其他两个.我使用Spring JDBC ResultSetExtractor将ResultSet转换为我的对象,其大致如下所示:

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;

但是,由于此查询有联接,当我限制结果数量时,我实际上限制了JOINED结果的数量(即,因为客户端将显示为他们拥有的帐户类型数量的多倍,LIMIT不会应用客户端数量,但客户端数量* accountTypes,这不是我想要的).

我想出的唯一解决方案是从查询删除LIMIT(和OFFSET,因为这也是错误的)并以编程方式应用它们:

List<Client> allClients = jdbcTemplate.query....
List<Client> result = allClients.subList(offset, offset+limit);

但这显然不是一个非常好的,有效的解决方案.有没有更好的办法?

解决方法:

如何写一个问题让你思考,实际上有助于为你自己的问题想象一个解决方案.

我能够通过简单地将查询分页部分添加到我的主查询的子查询而不是主查询本身来解决这个问题.

例如,而不是做:

SELECT client.id, client.name ...
FROM clients AS client
LEFT JOIN client_account_types AS cat ON client.id = cat.client_id
FULL JOIN account_types AS at ON cat.account_type_id = at.id
ORDER BY client.name ASC
LIMIT 10 OFFSET 30;

我这样做:

SELECT client.id, client.name ...
FROM (
    SELECT * FROM clients
    ORDER BY name ASC
    LIMIT 10 OFFSET 0
) AS client
LEFT JOIN client_account_types AS cat ON client.id = cat.client_id
FULL JOIN account_types AS at ON cat.account_type_id = at.id;

希望这也有助于其他人.

相关文章

连接数据库的方式:第一种方式:ODBC:开放数据库连接是微软...
JDBCRequest 使用VariableNamesmysql:数据库连接池对象var...
 1.JDBCDBC(JavaDataBaseConnectivity):Java数据库连接技术...
1.需要jar包的支持:java.sqljavax.sqlmysql-conneter-java....
1.简介Activiti是一个业务流程管理(BPM)框架,它是覆盖了业务...
1.JDBC体系系统一组规范:接口JDBC接口(API)包括两个层次:...