MySQL DISTINCT按permno去重失效及GROUP BY计算总收益报错解决
CRSP股票收益查询问题解决方案
问题1:DISTINCT无法按permno完成去重
根本原因
- DISTINCT的去重逻辑是对SELECT语句中所有返回字段的组合做整体去重,而非仅针对
permno字段去重。 - 你的关联条件仅匹配了
permno,未关联crsp.dsenames表的名称生效时间范围。该表本身记录了单个permno全生命周期内不同时段的ticker、comnam变更记录,直接关联会让同一permno的日度收益和所有历史名称记录交叉匹配,产生多条同permno、同ret但不同ticker/comnam的行。由于这些行的字段组合存在差异,DISTINCT无法将其识别为重复行。
解决方法
- 关联
crsp.dsenames时补充时间匹配规则,让交易日期落在名称的有效起止区间内(CRSP表自带namedt(名称生效日)、namendt(名称失效日)字段),从根源上过滤不相关的历史名称记录。 - 若匹配时间后仍存在同permno的多条名称记录,通过窗口函数为每个permno下的名称记录按生效时间打序号,仅取最新生效的唯一一行,替代无差别的
DISTINCT。
MySQL兼容的基础去重查询示例
SELECT permno, date, ret, ticker, comnam FROM ( SELECT a.permno, a.date, a.ret, b.ticker, b.comnam, ROW_NUMBER() OVER (PARTITION BY a.permno, a.date ORDER BY b.namedt DESC) AS rn FROM crsp.dsf a INNER JOIN crsp.dsenames b ON a.permno = b.permno -- 匹配名称有效时间范围 AND a.date BETWEEN b.namedt AND b.namendt WHERE a.date BETWEEN '2020-11-09' AND '2020-11-10' ) t WHERE rn = 1
问题2:GROUP BY计算总收益时报错
根本原因
- 原查询的SELECT子句中,
comnam字段和聚合计算字段exp(sum(log(1+ret)))之间缺失逗号分隔,会直接触发语法解析错误。 - MySQL开启
only_full_group_by严格模式时,SELECT返回的字段要么是GROUP BY中包含的分组字段,要么是被聚合函数包裹的计算值。你在语句中同时返回了未做聚合的date、ret、ticker、comnam字段,且仅按permno分组,会直接触发语法报错。 - 查询逻辑存在偏差:你需要计算的是区间总收益、并按总收益排序筛选最差的20只股票,但原语句直接使用单日
ret排序,选出的结果并非区间维度的最差表现股票。
解决方法
- 拆分查询逻辑:先按
permno分组计算区间复利总收益,按总收益升序排序(收益越低表现越差)取前20只标的,再关联名称表匹配对应的股票代码、公司名。 - 总收益计算的
exp(sum(log(1+ret)))为CRSP官方推荐的复利计算写法,注意需要减1得到净收益率,否则计算结果为本利和而非实际收益。
MySQL兼容的完整查询示例
WITH stock_lowest_return AS ( -- 第一步:计算每个permno在目标区间的总收益,筛选收益最低的20只 SELECT permno, EXP(SUM(LN(1 + ret))) - 1 AS total_return FROM crsp.dsf WHERE date BETWEEN '2020-11-09' AND '2020-11-10' GROUP BY permno -- 按总收益从低到高排序,获取表现最差的标的 ORDER BY total_return ASC LIMIT 20 ), name_mapping AS ( -- 预先生成每个permno对应的最新有效名称 SELECT permno, ticker, comnam FROM ( SELECT permno, ticker, comnam, ROW_NUMBER() OVER (PARTITION BY permno ORDER BY namedt DESC) AS rn FROM crsp.dsenames ) t WHERE rn = 1 ) -- 关联返回最终结果 SELECT s.permno, s.total_return, nm.ticker, nm.comnam FROM stock_lowest_return s INNER JOIN name_mapping nm ON s.permno = nm.permno
内容的提问来源于stack exchange,提问作者Michale
相关产品推荐
相关产品推荐

