我有一个组织内成员持有的历史职位任期表 (tbl_tenue)。每个职位一次只能由一个人担任,但一个人可以顺序或同时担任多个职位。我想检查该表的完整性,依次获取每个职位任期记录,然后将其与表中的所有其他记录进行比较,以寻找(错误)与同一职位的其他任期重叠。
我编写了一个工作查询(如下),它在通过 test_tenure_id、position_id 以及特定任期的开始和结束日期(见下文)时返回重叠的详细信息。此查询返回tenure_id、member_id、member_sn、date_started、date_ended 和重叠原因。
任何人都可以帮助我使用 sql 现在针对同一个 tbl_tenue 表运行此查询,每次将数据从 tbl_tenue 中的一行传递给它,这样我就可以测试每条记录是否与其他记录重叠(当然除了它本身)并返回数据从记录及其所有重叠?
(我意识到,如果我能做到这一点,那么我应该能够避免使用连接将tenure_id 传递给 WHERE 子句,并且也避免使用连接传递日期,但我看不到如何做到这一点此刻,所以任何帮助都会很好)
下面的查询使用下表,为此问题进行了简化
TABLE tbl_member
( member_id INT AUTO_INCREMENT, -- pk
member_sn` varchar(50) , --surname
<other stuff>
)
TABLE tbl_tenure
(tenure_id INT AUTO_INCREMENT, -- pk
member_id INT -- fk to tbl_member
position_id -- fk to table of position titles
date_started DATE
date_ended DATE -- will be NULL if still in post
)
-- test data for query
SET @the_test_tenure_start_date = '2016-05-13' ;
SET @the_test_tenure_end_date = '2016-10-05';
SET @the_test_position_id = 18;
SET @the_test_tenue_id = 122;
-- the query to return overlaps with data from a given tenure record
SELECT
tbl_tenure.tenure_id,
tbl_tenure.member_id,
tbl_member.member_sn,
tbl_tenure.date_started,
tbl_tenure.date_ended,
CASE
WHEN @the_test_tenure_end_date <= IFNULL(date_ended, CURDATE()) -- test end date <= existing end date
AND @the_test_tenure_start_date >= date_started -- test start date >= existing start date
THEN 'Test dates fall completely inside an existing tenure'
WHEN @the_test_tenure_end_date >= IFNULL(date_ended, CURDATE()) -- test end date >= existing end date
AND @the_test_tenure_start_date <= date_started -- test start date <= existing start date
THEN 'An existing tenure falls completely inside test dates'
WHEN @the_test_tenure_start_date >= date_started -- test start date >= existing start date
AND @the_test_tenure_start_date <= IFNULL(date_ended, CURDATE()) -- test start date <= existing end date
THEN 'Test start date overlaps with an existing tenure'
WHEN @the_test_tenure_end_date >= date_started -- test end date >= existing start date
AND @the_test_tenure_end_date <= IFNULL(date_ended, CURDATE()) -- test end date <= existing end date
THEN 'Test end date overlaps with an existing tenure'
END AS reason
FROM
tbl_tenure
INNER JOIN tbl_member
ON tbl_tenure.member_id = tbl_member.member_id
WHERE ( -- there is an overlap (see qry 2.2 http://salman-w.blogspot.co.uk/2012/06/sql-query-overlapping-date-ranges.html
@the_test_tenure_end_date >= date_started)
AND
IFNULL(date_ended, CURDATE()) >= @the_test_tenure_start_date
)
AND tbl_tenure.position_id = @the_test_position_id -- position to be tested
AND tbl_tenure.tenure_id <> @the_test_tenue_id -- don't look at the test tenure record
ORDER BY tbl_tenure.date_started ASC;
为了澄清这个问题,我正在寻找的输出是这样的,注意tenure_id 132,其中成员被记录为与自己重叠
tenure_id | member_id | position_id | start_date | end_date | overlapping_member_id | overlapping_tenure_id | overlapping_start_date |overlapping_end_date | overlap_reason
123 | 2 | 6 | 2016-02-01 | 2016 02-01 | 7 | 456 | 2016-01-05 | 2016-01-10 |'Test start date overlaps with an existing tenure'
125 | 2 | 8 | 2016-02-01 | 2016 03-01 | 8 | 459 | 2016-01-0 | 2016-02-01 |'Test end date overlaps with an existing tenure'
129 | 4 | 7 | 2016-03-10 | 2016 04-01 | 6 | 501 | 2016-03-2 | 2016-03-25 |'An existing tenure falls completely inside test dates'
132 | 4 | 7 | 2016-01-01 | 2016 04-01 | 4 | 505 | 2016-03-01 | 2016-04-01 |'Test end date overlaps with an existing tenure'
135 | 9 | 3 | 2016-05-01 | 2016 07-01 | 9 | 520 | 2016-04-0 | 2016-08-01 |'Test dates fall completely inside an existing tenure'