【问题标题】:SQL Server Matching Records over a Range of Valid TimesSQL Server 匹配有效时间范围内的记录
【发布时间】:2013-09-05 04:39:04
【问题描述】:

我有一个行程表,其中包含在城市不同地区行驶的个别汽车的信息(开始时间、结束时间、开始位置、结束位置等)​​。我还有一张表,其中包含半定期(每 15 到 30 分钟)测量的所述城市的天气状况(温度、降水量等)。

Trip Table
| TripID  |        StartTime        |       EndTime           | ....
| 1       | 2012-01-10 03:50:00.163 | 2012-01-15 04:15:40.163 |
| 2       | 2012-01-10 03:59:00.113 | 2012-01-15 04:44:25.025 |
| 3       | 2012-01-10 04:10:00.127 | 2012-01-15 04:35:36.064 |

Weather Table
| WeatherID |    ReadingTime      | .... 
| 1         | 2012-01-10 03:45:00 | 
| 2         | 2012-01-10 04:02:05 | 
| 3         | 2012-01-10 04:30:34 | 
| 4         | 2012-01-10 04:45:23 | 

这些天气读数是离散的,因此为了使其(更)连续,我假设 id 在以读取时间为中点的范围内有效。例如:

  • WeatherID 1 条件在 3:45 到 3:53:525 期间有效
  • WeatherID 2 条件在 3:53:525 到 3:16:195 期间有效

我想在行程表中添加一个外键,该表将每次行程与天气相关联,其中大部分行程都存在。例如,TripID 2 需要 42 分钟才能完成,这发生在两个天气读数(WeatherID 2 和 3)上。所以 WeatherID 3 将被分配给tripID 2 记录,因为更多的行程发生在weatherID 3 而不是weatherID 2 下。

我知道这有点复杂,但是可以使用 SQL 来解决吗?任何帮助表示赞赏。感谢。

【问题讨论】:

  • 您使用的是什么关系型数据库?您是否考虑过使用 VIEW 来实现这种关系,而不使用离散的 FK 关系?
  • 我认为您不应该使用离散的 FK 关系。我的建议是选择最接近 StartTime 和 EndTime 的阅读时间,然后选择这些时间之间的天气数据。如果您真的想要,您可以添加一个字段(或实际上是这两者之间的绑定表)用作 FK,并在触发器中执行上述操作以填充该字段。
  • 如果旅行需要两种以上的天气条件,而没有一种天气条件可以覆盖超过一半的旅行时间怎么办?你想要跨越旅程最大部分的天气状况吗?还是根本没有天气状况?

标签: sql join relational-database grouping


【解决方案1】:

如果您使用的是最新版本的 SQL Server,要获取涵盖大部分行程的天气状况,请尝试:

with tripSegs (wxId, starttime, endTime)
As (Select w.WeatherId, 
         coalesce(n.readingTime, w.ReadingTime) startTime,
         coalesce(p.readingTime, w.ReadingTime) endTime
    From Weather w
    left Join weather p on p.ReadingTime =
        (Select Max(ReadingTime)
            From Weather
            Where ReadingTime < w.ReadingTime)
    left Join weather n on n.ReadingTime =
        (Select Min(ReadingTime)
            From Weather
            Where ReadingTime > w.ReadingTime)) 
Select t.tripId, w.wxId, 
    case when w.startTime < t.startTime then t.startTime else w.startTime end startTime,
    case when w.endTime > t.endtime then t.endtime else w.endtime end endtime,
    case when w.startTime < t.startTime then t.startTime else w.startTime end -
    case when w.endTime > t.endtime then t.endtime else w.endtime end elapsedEffectiveTime
From Trips t Join tripSegs w 
     On w.starttime < t.endtime 
 And w.endtime > t.startTime
Where case when w.startTime < t.startTime then t.startTime else w.startTime end -
      case when w.endTime > t.endtime then t.endtime else w.endtime end >  
   (Select Max(case when w.startTime < t.startTime then t.startTime else w.startTime end -
               case when w.endTime > t.endtime then t..endtime else w.endtime end) 
    from Trips t
    Join tripSegs w On w.starttime < t.endtime 
        And w.endtime > t.startTime)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多