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。你能帮我吗租赁