Tsql T-SQL,从几个分组表中选择

Tsql T-SQL,从几个分组表中选择,tsql,select,grouping,Tsql,Select,Grouping,我有一个非常艰巨的任务,我不知道如何开始 假设我们有桌子: Car - CarId (int) - OperatorId (int) - ProductionDate (date) Person - PersonId (int) - Name (vchar) CarRentHistory - HistoryId (int) - CarFk (int) - OperatorFk (int) - ChangeDate (date) 每辆车都是租来的。它的生产日期是它第一次被租

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

假设我们有桌子:

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
所以这辆车是由Person1(按生产)在2013年1月1日租下的,后来mont Person2租下了它(2013年2月2日)

结果应该是这样的:

法案,Car1,平均=((2013/2/2-2013/1/1)+(现在-2013/3/3))/2

最大,Car1,平均=(2013/3/3-2013/2/2)/1


请帮助:(

第一步是找出每个租期的长度。为此,请执行相关子查询,找到与开始日期一致的结束日期。如果我们找不到行,这意味着租金是当前的,今天的日期将是结束日期(我假设).一旦你计算出每次租车的时间长度,就只需按人和车进行分组并取平均值

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
以下是完整的查询:

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 FIDLE,显示正在运行的查询。

第一步是找出每个租期的长度。为此,请执行相关子查询,找到与开始日期一致的结束日期。如果找不到行,则表示租期是当前的,而今天的日期就是结束日期(我假设).一旦你计算出每次租车的时间长度,就只需按人和车进行分组并取平均值

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
以下是完整的查询:

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 FIDLE,显示正在运行的查询。

如果您使用SQL Server 2012,您可以充分利用新的LEAD windowed函数。它将为您提供下一行的列值,这对于构建每个租赁期的对非常有用

这个想法和Chad Henderson的答案是一样的:首先构建配对,然后计算平均值

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 Server 2012,您可以充分利用新的LEAD windowed函数。它将为您提供下一行的列值,这对于构建每个租赁期的对非常有用

这个想法和Chad Henderson的答案是一样的:首先构建配对,然后计算平均值

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


结果当然是一样的,但执行计划可能更好。

非常感谢。我还有一个问题,因为问题已经改变。在表Car中,我们有一个额外的列,名为CreatorFk。它是第一个租车的人。因此,我们必须检查的第一个日期是ProductionDate+CreatorFk,然后是normal来自CarrenthHistory的ly。你能帮忙吗?非常感谢。我有另一个问题,因为问题已经改变。在表Car中,我们有一个额外的列,名为CreatorFk。这是第一个租车的人。所以我们要检查的第一个日期是ProductionDate+CreatorFk,然后通常来自CarrenthHistory。你能帮我吗租赁