从多个记录中仅选择最近期的日期记录

时间:2014-04-01 14:47:34

标签: sql sql-server

使用MS_SQL

我有一个查询,我试图从未来事件列表中仅返回NEXT事件(基于今天的日期) - 因此数据库中的记录(entity_name)可能会有多个未来事件发生。

到目前为止,这是我的代码:

select fut.event_id, ent.entity_name, evt.event_datetime_utc
from evt_v1.ce_events_coverage_future fut
left join evt_v1.ce_events evt
on evt.event_id=fut.event_id
left join edm_v1.edm_entity ent
on ent.factset_entity_id=fut.factset_entity_id
left join edm_v1.edm_security_entity_map map
on map.factset_entity_id=ent.factset_entity_id
left join evt_v1.ce_event_types typ
on typ.event_type=evt.event_type
left join evt_v1.ce_market_times mkt
on mkt.market_time=evt.market_time
left join evt_v1.ce_fiscal_periods fis
on fis.fiscal_period=evt.fiscal_period
where map.isin in
('US38259P5089',
'US0378331005')
and evt.event_type='ER'
and evt.event_datetime >=GetDate()
order by ent.entity_name asc, event_datetime asc

返回以下结果:

event_id    entity_name event_datetime_utc
4097237 APPLE INC   2014-04-22 00:00:00.000
4188165 APPLE INC   2014-07-22 00:00:00.000
4270116 APPLE INC   2014-10-20 00:00:00.000
4339538 APPLE INC   2015-01-20 00:00:00.000
4097141 GOOGLE INC  2014-04-16 00:00:00.000
4188066 GOOGLE INC  2014-07-17 00:00:00.000
4269906 GOOGLE INC  2014-10-16 00:00:00.000
4339013 GOOGLE INC  2015-01-22 00:00:00.000

我想要返回的是每个entity_name最迫切的记录:

4097237 APPLE INC   2014-04-22 00:00:00.000
4097141 GOOGLE INC  2014-04-16 00:00:00.000

我确信这很简单,但我不确定这是否最好通过使用DATE函数或某种RANK函数(或两者都没有!)?

先谢谢你的帮助, 即

2 个答案:

答案 0 :(得分:2)

您可以使用rank()row_number()

with t as (<your query here>)
select event_id, entity_name, event_datetime_utc
from (select t.*,
             row_number() over (partition by entity_name
                                order by event_datetime_utc asc
                               ) as seqnum
      from t
     ) t
where seqnum = 1;

答案 1 :(得分:0)

首先,您可以使用子查询来查找这些值。这取决于evt_v1.ce_events.event_datetime不为空的假设。此外,如果确定“next”需要map.isin上的附加条件,则只需展开子查询即可。

Select fut.event_id, ent.entity_name, evt.event_datetime_utc
From evt_v1.ce_events_coverage_future As fut
    Join evt_v1.ce_events As evt
        On evt.event_id = fut.event_id
    Join edm_v1.edm_entity As ent
        On ent.factset_entity_id = fut.factset_entity_id
    Join edm_v1.edm_security_entity_map As map
        On map.factset_entity_id = ent.factset_entity_id
    Left Join evt_v1.ce_event_types As typ
        On typ.event_type = evt.event_type
    Left Join evt_v1.ce_market_times As mkt
        On mkt.market_time = evt.market_time
    Left Join evt_v1.ce_fiscal_periods As fis
        On fis.fiscal_period = evt.fiscal_period
Where map.isin In( 'US38259P5089','US0378331005' )
    And evt.event_type = 'ER'
    And evt.event_datetime =    (
                                Select Min( evt1.event_datetime )
                                From evt_v1.ce_events_coverage_future As fut1
                                    Join evt_v1.ce_events As evt1
                                        On evt1.event_id = fut1.event_id
                                    Join edm_v1.edm_entity As ent1
                                        On ent1.factset_entity_id = fut1.factset_entity_id
                                Where ent1.entity_name = ent.entity_name
                                    And evt1.event_datetime >= CURRENT_TIMESTAMP
                                )
Order By ent.entity_name Asc, evt.event_datetime Asc

其次,你已经在很多地方使用了Left Joins,它们没有任何区别。具体来说,您在edm_v1.edm_security_entity_map上有一个左连接,但在Where子句中,您要求map.isin凭借您的In函数具有值,从而有效地将此Left Join转换为内部Join。 edm_v1.edm_security_entity_map表也是如此。