Q:

Sql: determine an event's active period from start date and end date split in 2 tables

Sql problem: determine an event's active period from start date and end date split in 2 tables
This is an adhoc report that I need to produce. I was provided 2 extract files pertaining to events (csv). I intend to insert these extracts to a single sql table #temp_events.
File 1:
event, start date
Core training, 01Jan2011
Certification reviews, 23Feb2011
Core training, 15May2011
Abc Event, 24Nov2011

File 2:
event, end date
Core training, 05Jan2011
Certification reviews, 24Feb2011
Core training, 18May2011
Abc Event, 30Nov2011

I want to insert into a #temp_events, wherein an entry will define an event's active period. Note that there is no FK, as this is the primary problem at hand... the only way to relate data is via event name however there could be multiple occurrences of an event. An event's end cannot be calculated since there is no data that defines how long an event is. These are the restrictions that I need to deal with as extract provider has stipulated, unfortunately.
Can anyone provide suggestions for the logic that I need to code, so that I can reliably link event's in File 1 to File 2 even though there is no natural key/id/FK? Any obvious loophole that I may run into?

A:

There you go:
CREATE TABLE eventstart
        ( event VARCHAR NOT NULL
        , zdate date
        );
INSERT INTO eventstart(event,zdate) VALUES
 ( 'Core training' , '2011-01-01' )
,( 'Certification reviews' , '2011-02-23' )
,( 'Core training' , '2011-05-15' )
,( 'Abc Event' , '2011-11-24' )
        ;

CREATE TABLE eventend
        ( event VARCHAR NOT NULL
        , zdate date
        );
INSERT INTO eventend(event,zdate) VALUES
 ('Core training' , '2011-01-05' )
,('Certification reviews' , '2011-02-24' )
,('Core training' , '2011-05-18' )
,('Abc Event' , '2011-11-30' )
        ;

WITH    s AS (
        SELECT ss.event, ss.zdate
        , ROW_NUMBER() OVER( PARTITION BY ss.event ORDER BY ss.zdate) AS zrnk
        FROM eventstart ss
        )
        ,e AS (
        SELECT ee.event, ee.zdate
        , ROW_NUMBER() OVER( PARTITION BY ee.event ORDER BY ee.zdate) AS zrnk
        FROM eventend ee
        )
SELECT s.event
       , s.zdate AS sdate
       , e.zdate AS edate
FROM s
LEFT JOIN e ON e.event = s.event AND s.zrnk = e.zrnk
WHERE s.zdate <= COALESCE(e.zdate , s.zdate) -- safety valve ;-)
        ;

Note: the above query is very rude. It relies on the borderconditions given by the OP, that there will be a matching end-record for every start record. If not: YMMV
Result:
CREATE TABLE
INSERT 0 4
CREATE TABLE
INSERT 0 4
         event         |   sdate    |   edate    
-----------------------+------------+------------
 Abc Event             | 2011-11-24 | 2011-11-30
 Certification reviews | 2011-02-23 | 2011-02-24
 Core training         | 2011-01-01 | 2011-01-05
 Core training         | 2011-05-15 | 2011-05-18
(4 rows)

