使用 hsql db 时查询得到“无效顺序”,而 Mysql 没有结果必须只有一列

问题描述

虽然此查询MysqL 数据库中运行良好:

SELECT disTINCT user_id  
FROM table_name 
WHERE user_name IN (:userNameList) 
  AND user_type IN ('client','vip')   
ORDER BY user_login_time DESC
LIMIT 10  OFFSET 0

当我尝试通过 Hsql 运行相同的查询时,出现此错误

嵌套异常是 java.sql.sqlSyntaxErrorException: invalid ORDER BY expression in statement [SELECT disTINCT user_id FROM table_name WHERE user_name IN (:userNameList) AND user_type IN ('client','vip') ORDER BY user_login_time desc LIMIT 10 OFFSET 0]

解决方法

这个问题的解决方案需要我改变查询:在HSQL中我们必须按列选择顺序。没有它,我们就会收到这个错误。

SELECT DISTINCT user_id,user_login_time  
FROM table_name 
WHERE user_name IN (:userNameList) 
  AND user_type IN ('client','vip')   
ORDER BY user_login_time DESC
LIMIT 10  OFFSET 0

但是这个解决方案返回两列而不是一列。

通过使用 JDBCTAmplate,我找到了只返回一列的方法

String query = "SELECT DISTINCT user_id,user_login_time  FROM table_name WHERE user_name IN (:userNameList) AND user_type IN ('client','vip') ORDER BY user_login_time DESC LIMIT 10  OFFSET 0";
    
List<String> userIds = new ArrayList<String>();
List<String> userIdList = List.of("12345667","123443235");
Map<String,Object> sqlParameterSource = new HashMap<>();
sqlParameterSource.put("userNameList",userIdList);
                
userIds = namedParamJDBCTemplate.query(query,new MapSqlParameterSource(sqlParameterSource),new ResultSetExtractor<List>() {
                 
                    @Override
                    public List extractData(ResultSet resultSet) throws SQLException,DataAccessException {
                        List<String> listRes = new ArrayList<String>();
                        while (resultSet.next()) {
                            listRes.add(resultSet.getString(USER_ID));
                        }
                        return listRes;
                    }
                });

这个解决方案允许我通过 HSQL 运行查询,结果仍然只得到一列。

,

这样的查询只返回 user_id COLUMN

SELECT user_id FROM 
  ( SELECT DISTINCT user_id,user_login_time  
    FROM table_name 
    WHERE user_name IN (:userNameList) 
    AND user_type IN ('client','vip')   
    ORDER BY user_login_time DESC
    LIMIT 10  OFFSET 0 )

如果一个用户有多次登录,MySQL 查询会为该用户返回一行,其中一个登录时间用于排序,这可能不是该用户的最后一次登录时间。

最好使用 GROUP BY 以确保结果一致:

SELECT user_id 
FROM table_name 
WHERE user_name IN (:userNameList) 
  AND user_type IN ('client','vip')   
GROUP BY user_id
ORDER BY MAX(user_login_time) DESC
LIMIT 10  OFFSET 0