1

我有非常艰巨的任务,我不知道如何开始。

假设我们有表格:

Car
 - CarId (int)
 - OperatorId (int)
 - ProductionDate (date)

Person
 - PersonId (int)
 - Name (vchar)

CarRentHistory
 - HistoryId (int)
 - CarFk (int)
 - OperatorFk (int)
 - ChangeDate (date)

每辆车都是租来的。它的生产日期是它被租用的第一次。

一个人可以多次租用同一辆车,但每辆车在一瞬间只能有一个操作员。

问题是如何为每个人和每辆车(按人和车分组)平均租金时间选择数据。

Example:
Person1:    
 - PersonId = 1,
 - Name = Bill,

Person2:    
 - PersonId = 2,
 - Name = Max,

Car1:
 - CarId = 1,
 - Operator = 1,
 - ProductionDate = 2013/1/1,

CarRentHistory:    
 - HistoryId=1, CarFk=1, OperatorFk=1, Date = 2013/1/1
 - HistoryId=2, CarFk=1, OperatorFk=2, Date = 2013/2/2
 - HistoryId=3, CarFk=1, OperatorFk=1, Date = 2013/3/3

所以 Car 是在 2013 年 1 月 1 日由 Person1 (按生产)租用的,然后在一个月后 Person2 租了它(2013 年 2 月 2 日)。

结果应该是这样的:

比尔,Car1,平均值 = ( (2013/2/2 - 2013/1/1) + (NOW - 2013/3/3))/2

Max, Car1, Average = (2013/3/3 - 2013/2/2) / 1

请帮忙, :(

4

2 回答 2

1

第一步是找出每个租期的长度。为此,请执行一个相关子查询,以找到与开始日期一致的结束日期。如果我们没有找到一行,这意味着租金是当前的,今天的日期将是结束日期(我假设)。一旦你知道了每次租赁的长度,就可以简单地按人和汽车分组并取平均值。

这是完整的查询:

with RentalLengths as (
  select P.Name, H.CarFk,
    datediff(Day, ChangeDate,
      isnull((
        select min(ChangeDate)
        from CarRentHistory H2
        where H2.CarFk = H.CarFk
          and H2.ChangeDate > H.ChangeDate
        ), CURRENT_TIMESTAMP)) as Length
  from CarRentHistory H
  inner join Person P on P.PersonId = H.OperatorFk
)
select Name, CarFk, AVG(Length)
from RentalLengths
group by Name, CarFk

是一个显示查询的 SQL Fiddle。

于 2013-06-04T16:32:04.240 回答
0

If you use SQL Server 2012, you can make good use of the new LEAD windowed function. It will give you the value of a column for the next row, which makes it very useful to build the pairs of each rental period.

The idea is the same as Chad Henderson's answer: first build the pairs, then compute the average.

with RentalPeriod as (
  select
    CarFk, OperatorFk, ChangeDate, 
    lead(ChangeDate) over (partition by CarFk order by ChangeDate) as NextChangeDate
  from CarRentHistory
)
select
  CarFk, OperatorFk, 
  avg(datediff(day, 
               ChangeDate, 
               isnull(NextChangeDate, getdate()))) as AverageDays
from RentalPeriod
group by CarFk, OperatorFk

SQL Fiddle

The result is of course the same but the execution plan is probably better.

于 2013-06-04T17:09:38.210 回答