1

我有一个简单的就业历史数据库,我存储条目 ID、用户 ID、他们的工作、开始和结束日期。可能有一些重叠的条目。我需要确定在给定的时间段内没有给定时间范围的中断。

所以 user_id 1 有这样的工作历史

Marketing - 01/01/2013 to 19/05/2013
Sales - 01/01/2011 to 01/05/2012
Admin - 01/01/2010 to 31/12/2010

我实际上将日期存储为 unix 时间戳。在三年的历史中,user_id 1 在他们的销售工作和营销工作之间有超过 6 个月的休息时间。我如何向他们标记此内容,以便他们可以提供此期间的条目。

4

2 回答 2

2

这个问题比看起来更难,因为你的工作经历可能有重叠。事实上,你可以有一个工作时期完全“在”另一个时期,或者在任一端重叠。

您正在寻找的是一个与开始日期有间隔且不在另一个工作期间的 EndDate。因此,让我们使用相关子查询来获取结束日期之后的下一个开始日期,如下所示:

     select t.*,
             (select StartDate
              from t t2
              where t2.user_id = t.user_id and
                    t2.StartDate > t.EndDate
              order by StartDate desc
              limit 1
             ) nextStartDate
      from t

现在,问题是:这个时期是否被另一个时期所覆盖。为此,我将使用一个复杂的where子句:

select t.*
from (select t.*,
             (select StartDate
              from t t2
              where t2.user_id = t.user_id and
                    t2.StartDate > t.EndDate
              order by StartDate desc
              limit 1
             ) nextStartDate
      from t
     ) t
where not exists (select 1
                  from t t2
                  where t2.StartDate <= t.EndDate and
                        t2.EndDate >= t.nextStartDate
                 ) and
      (t.EndDate is null or t.EndDate > now())

根据您处理重叠的方式,您可能希望在日期之间留出几天的延迟。

这应该会返回表中存在空白的所有记录。在您的示例数据中,这将返回今天的记录(2013-05-19)。“销售”记录之后有一个缺口,直到“营销”职位。“营销”将在未来返回,因为它会在过去结束。

实际上,一个间隙可能会导致返回多条记录。当有重叠时会发生这种情况,我将仅用数字来解释:(0, 10), (5, 12), (15, 20)。从 12/13 开始的差距将影响这两个记录。如果这是一个问题,那么可以修复查询,尽管我首先想到如何修复它会使查询更加复杂。

据推测,您还将过滤用户 ID,您可以将其放在最外面的where子句中。

于 2013-05-19T15:40:35.297 回答
0

你会寻找这样的东西:

<?php
    $time_allowed = '1 month';

    $person = [
        [
            1305819929, // 19-05-11
            1337442341  // 19-05-12
        ],

        [
            1337442341, // 19-05-12
            1345933614  // 26-08-12
        ],

            // almost 4 month gap here - this will result in flagged() getting triggered

        [
            1355935614, // 19-12-12
            1368978787  // 19-05-13
        ]
    ];

    $time_allowed = strtotime('now') - strtotime("-{$time_allowed}");

    foreach($person as $key => $job)
    {
        if( ! isset($person[$key + 1]))
        {
            if($job[1] !== 'current' && (strtotime('now') - $job[1]) > $time_allowed)
            {
                flagged();
            }
        }
        else
        {
            if(($person[$key + 1][0] - $job[1]) > $time_allowed)
            {
                flagged();
            }
        }
    }

    function flagged()
    {
        // user flagged
    }

显然$person会从数据库中抓取。脚本应该是不言自明的,

于 2013-05-19T15:39:50.627 回答