SQL查询按日期范围折叠重复值
无论我们在哪里有空,OP都希望“to”月与“from”月相同,所以我们只需使用coalesce:coalesce(last_am,am).由于last删除了任何空值,因此我们的连接不需要是外连接. > select a.eid,b.m,b.y,c.m,c.y,a.v from cm_result_data a join cm_abs_month b on ( a.eid = b.eid and a.am = b.am) join cm_abs_month c on ( a.eid = c.eid and coalesce( a.last_am - 1,(select max(am) from cm_abs_month d where d.eid = a.eid ) ) = c.am) order by 1,3,2,5,4; +-----+------+------+------+------+------+ | eid | m | y | m | y | v | +-----+------+------+------+------+------+ | 100 | 1 | 2008 | 2 | 2008 | 80 | | 100 | 3 | 2008 | 3 | 2008 | 90 | | 100 | 4 | 2008 | 4 | 2008 | 80 | | 200 | 1 | 2008 | 2 | 2008 | 80 | | 200 | 3 | 2008 | 3 | 2008 | 90 | | 200 | 4 | 2008 | 4 | 2008 | 80 | +-----+------+------+------+------+------+ 通过加入我们获得OP想要的输出. 不是说我们必须加入.碰巧,我们的absolute_month函数是双向的,所以我们可以重新计算年份并从中抵消月份. 首先,让我们来处理添加“封顶”月份: > create or replace view cm_capped_result as select eid,am,coalesce( last_am - 1,(select max(b.am) from cm_abs_month b where b.eid = a.eid) ) as last_am,v from cm_result_data a; 现在我们得到按OP格式化的数据: select eid,( (am - 1) % 12 ) + 1 as sm,floor( ( am - 1 ) / 12 ) as sy,( (last_am - 1) % 12 ) + 1 as em,floor( ( last_am - 1 ) / 12 ) as ey,v from cm_capped_result order by 1,4; +-----+------+------+------+------+------+ | eid | sm | sy | em | ey | v | +-----+------+------+------+------+------+ | 100 | 1 | 2008 | 2 | 2008 | 80 | | 100 | 3 | 2008 | 3 | 2008 | 90 | | 100 | 4 | 2008 | 4 | 2008 | 80 | | 200 | 1 | 2008 | 2 | 2008 | 80 | | 200 | 3 | 2008 | 3 | 2008 | 90 | | 200 | 4 | 2008 | 4 | 2008 | 80 | +-----+------+------+------+------+------+ 还有OP想要的数据.所有SQL都应该在任何RDBMS上运行,并且被分解为简单,易于理解且易于测试的视图. 是重新加入还是重新计算?我会把这个(这是一个技巧问题)留给读者. (如果您的RDBMS不允许在视图中使用分组,则必须首先加入,然后分组或分组,然后使用相关子查询提取月份和年份.这留给读者练习.) Jonathan Leffler在评论中问道,
嗯,你是完全正确的,OP没有指明.也许存在(未提及的)前提条件,即没有间隙.在没有要求的情况下,我们不应该尝试围绕可能不存在的东西进行编码.但事实是,差距使得“加入”战略失败;在这些条件下,“重新计算”策略不会失败.我会说更多,但这将揭示我在上面提到的技巧问题中的诀窍. (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |