SQL聚合函数使用疑问:Sybase中分组聚合查询未返回预期单行结果的原因咨询
嘿,我来帮你拆解这个问题,搞清楚为啥你的两条查询行数一样,以及怎么拿到你想要的结果~
为啥第一条查询没返回单行结果?
你第一条查询的问题出在GROUP BY的逻辑用错了:
select CREATE_LOCATION, max(CREATE_DATE) from LOAN where BORROWER_ID=10 group by CREATE_DATE
你本来想找的是BORROWER_ID=10的所有记录里,CREATE_DATE最大的那一行(或几行)的信息,但你用GROUP BY CREATE_DATE相当于告诉Sybase:把数据按CREATE_DATE分成不同的组,每个组单独计算聚合值。
但这里的max(CREATE_DATE)对每个组来说,结果就是组内的CREATE_DATE本身(因为同一组的CREATE_DATE都是一样的)。再加上Sybase允许在SELECT里包含不在GROUP BY子句中的列(这不符合标准SQL,但Sybase有这个特性),它会把每个原始行的CREATE_LOCATION都保留下来,最终就导致返回的行数和原表中BORROWER_ID=10的记录数完全一致——相当于只是给每行加了个和CREATE_DATE一样的max(CREATE_DATE)列,根本没做你想要的“找最大值对应行”的操作。
为啥两条查询行数一致?
第二条查询就是直接取出所有BORROWER_ID=10的记录,而第一条查询因为上述的GROUP BY逻辑错误,本质上并没有对数据做聚合合并,只是给每行多算了一个冗余的max(CREATE_DATE)值,所以最终返回的行数自然和第二条完全相同,只是排序不同(第一条默认按GROUP BY的列CREATE_DATE降序排列,第二条是按数据存储的默认顺序返回)。
正确的查询写法
要拿到CREATE_DATE最大值对应的CREATE_LOCATION和CREATE_DATE,有两种常用的方法:
方法1:子查询先找最大值,再关联原表
这种方法兼容性好,适合所有版本的Sybase:
SELECT CREATE_LOCATION, CREATE_DATE FROM LOAN WHERE BORROWER_ID = 10 AND CREATE_DATE = (SELECT MAX(CREATE_DATE) FROM LOAN WHERE BORROWER_ID = 10)
如果有多个记录的CREATE_DATE都是最大值,这个查询会返回所有符合条件的行。
方法2:用窗口函数(Sybase ASE 15及以上版本支持)
如果你的Sybase版本支持窗口函数,用ROW_NUMBER()或RANK()会更灵活:
-- 只返回第一行最大值记录(如果有多个同最大值,随机选一个) SELECT CREATE_LOCATION, CREATE_DATE FROM ( SELECT CREATE_LOCATION, CREATE_DATE, ROW_NUMBER() OVER (ORDER BY CREATE_DATE DESC) AS rn FROM LOAN WHERE BORROWER_ID = 10 ) t WHERE rn = 1 -- 如果要返回所有最大值对应的记录,用RANK()代替ROW_NUMBER() SELECT CREATE_LOCATION, CREATE_DATE FROM ( SELECT CREATE_LOCATION, CREATE_DATE, RANK() OVER (ORDER BY CREATE_DATE DESC) AS rn FROM LOAN WHERE BORROWER_ID = 10 ) t WHERE rn = 1
内容的提问来源于stack exchange,提问作者TyneBridges

