Sql server 计算同一UnitID的不同行中日期之间的天数
我试图计算一个商业房地产空置的时间。我有每个入住该单元的租户的入住和迁出日期。由于数据位于同一行中,因此很容易计算每个租户的占用时间。但是,我想计算空置时间:从迁出前一个租户到迁入下一个租户之间的时间。这些日期显示在单独的行中 以下是我目前拥有的一个样本:Sql server 计算同一UnitID的不同行中日期之间的天数,sql-server,Sql Server,我试图计算一个商业房地产空置的时间。我有每个入住该单元的租户的入住和迁出日期。由于数据位于同一行中,因此很容易计算每个租户的占用时间。但是,我想计算空置时间:从迁出前一个租户到迁入下一个租户之间的时间。这些日期显示在单独的行中 以下是我目前拥有的一个样本: SELECT uni_vch_UnitNo AS UnitNumber, uty_vch_Code AS UnitCode, uty_int_Id AS UnitID, tul_int_FacilityId A
SELECT
uni_vch_UnitNo AS UnitNumber,
uty_vch_Code AS UnitCode,
uty_int_Id AS UnitID, tul_int_FacilityId AS FacilityID,
tul_dtm_MoveInDate AS Move_In_Date,
tul_dtm_MoveOutDate AS Move_Out_Date,
DATEDIFF(day, tul_dtm_MoveInDate, tul_dtm_MoveOutDate) AS Occupancy_Days
FROM TenantUnitLeases
JOIN units
ON tul_int_UnitId = uni_int_UnitId
JOIN UnitTypes
ON uni_int_UnitTypeId = uty_int_Id
WHERE
tul_int_UnitId = '26490'
ORDER BY tul_dtm_MoveInDate ASC
是否有办法按时间顺序为每一行分配一个id,并找出第2行的入住日期与第1行的迁出日期之间的差异,依此类推
提前感谢您的帮助。这需要一个窗口函数或相关子查询。目标是为每一行提供上一个移出日期,这又是该行的一个函数。在此上下文中,术语“窗口”意味着在比整个集合更小的范围内应用聚合函数 如果您有一个名为GetPreviousMoveOutDate的函数,那么这些参数将是要进行筛选的键,以及要在筛选中搜索的范围。因此,我们将传递
UnitID
作为此行的键和MoveInDate
,函数应返回传入日期之前相同单元的最新MoveOutDate
。通过在此日期之前获取最长日期,我们将确保仅获取以前的入住率(如果存在)
要在ANSI-SQL中使用子查询,只需添加select作为列。这应该适用于MS-SQL以及其他数据库平台;但是,它需要为表名使用别名,以便可以在查询中多次引用它们。我已经使用AS
语法用别名更新了示例SQL,尽管它看起来与表命名约定无关。我在units
表中添加了一个uni\u dtm\u UnitFirstAvailableDate
,以处理第一个空缺,但这可以是默认值:
SELECT
uni.uni_vch_UnitNo AS UnitNumber,
uty.uty_vch_Code AS UnitCode,
uty.uty_int_Id AS UnitID, tul_int_FacilityId AS FacilityID,
tul.tul_dtm_MoveInDate AS Move_In_Date,
tul.tul_dtm_MoveOutDate AS Move_Out_Date,
DATEDIFF(day, tul.tul_dtm_MoveInDate, tul.tul_dtm_MoveOutDate) AS Occupancy_Days,
-- select the date:
(SELECT MAX (prev_tul.tul_dtm_MoveOutDate )
FROM TenantUnitLeases AS prev_tul
WHERE prev_tul.tul_int_UnitId = tul.tul_int_UnitId
AND prev_tul.tul_dtm_MoveOutDate > tul.tul_dtm_MoveInDate
AND prev_tul.tul_dtm_MoveOutDate is not null
) AS previous_moveout,
-- use the date in a function:
DATEDIFF(day, tul.tul_dtm_MoveInDate,
ISNULL(
(SELECT MAX (prev_tul.tul_dtm_MoveOutDate )
FROM TenantUnitLeases AS prev_tul
WHERE prev_tul.tul_int_UnitId = tul.tul_int_UnitId
AND prev_tul.tul_dtm_MoveOutDate > tul.tul_dtm_MoveInDate
AND prev_tul.tul_dtm_MoveOutDate is not null
) , uni.uni_dtm_UnitFirstAvailableDate) -- handle first occupancy
) AS Vacancy_Days
FROM TenantUnitLeases AS tul
JOIN units AS uni
ON tul.tul_int_UnitId = uni.uni_int_UnitId
JOIN UnitTypes AS uty
ON uni.uni_int_UnitTypeId = uty.uty_int_Id
WHERE
tul.tul_int_UnitId = '26490'
ORDER BY tul.tul_dtm_MoveInDate ASC
这需要一个窗口函数或相关子查询。目标是为每一行提供上一个移出日期,这又是该行的一个函数。在此上下文中,术语“窗口”意味着在比整个集合更小的范围内应用聚合函数 如果您有一个名为GetPreviousMoveOutDate的函数,那么这些参数将是要进行筛选的键,以及要在筛选中搜索的范围。因此,我们将传递
UnitID
作为此行的键和MoveInDate
,函数应返回传入日期之前相同单元的最新MoveOutDate
。通过在此日期之前获取最长日期,我们将确保仅获取以前的入住率(如果存在)
要在ANSI-SQL中使用子查询,只需添加select作为列。这应该适用于MS-SQL以及其他数据库平台;但是,它需要为表名使用别名,以便可以在查询中多次引用它们。我已经使用AS
语法用别名更新了示例SQL,尽管它看起来与表命名约定无关。我在units
表中添加了一个uni\u dtm\u UnitFirstAvailableDate
,以处理第一个空缺,但这可以是默认值:
SELECT
uni.uni_vch_UnitNo AS UnitNumber,
uty.uty_vch_Code AS UnitCode,
uty.uty_int_Id AS UnitID, tul_int_FacilityId AS FacilityID,
tul.tul_dtm_MoveInDate AS Move_In_Date,
tul.tul_dtm_MoveOutDate AS Move_Out_Date,
DATEDIFF(day, tul.tul_dtm_MoveInDate, tul.tul_dtm_MoveOutDate) AS Occupancy_Days,
-- select the date:
(SELECT MAX (prev_tul.tul_dtm_MoveOutDate )
FROM TenantUnitLeases AS prev_tul
WHERE prev_tul.tul_int_UnitId = tul.tul_int_UnitId
AND prev_tul.tul_dtm_MoveOutDate > tul.tul_dtm_MoveInDate
AND prev_tul.tul_dtm_MoveOutDate is not null
) AS previous_moveout,
-- use the date in a function:
DATEDIFF(day, tul.tul_dtm_MoveInDate,
ISNULL(
(SELECT MAX (prev_tul.tul_dtm_MoveOutDate )
FROM TenantUnitLeases AS prev_tul
WHERE prev_tul.tul_int_UnitId = tul.tul_int_UnitId
AND prev_tul.tul_dtm_MoveOutDate > tul.tul_dtm_MoveInDate
AND prev_tul.tul_dtm_MoveOutDate is not null
) , uni.uni_dtm_UnitFirstAvailableDate) -- handle first occupancy
) AS Vacancy_Days
FROM TenantUnitLeases AS tul
JOIN units AS uni
ON tul.tul_int_UnitId = uni.uni_int_UnitId
JOIN UnitTypes AS uty
ON uni.uni_int_UnitTypeId = uty.uty_int_Id
WHERE
tul.tul_int_UnitId = '26490'
ORDER BY tul.tul_dtm_MoveInDate ASC
我真的不知道哪些表为您的查询提供了哪些列。今后请使用别名和dot对其进行限定 如果您使用的是SQL 2012或更高版本,那么您已经有了LEAD和LAG函数,它们可以完全满足您的需要:将“leading”或“laging”行放入当前行。看看这是否有效(希望它至少能让你开始):
我真的不知道哪些表为您的查询提供了哪些列。今后请使用别名和dot对其进行限定 如果您使用的是SQL 2012或更高版本,那么您已经有了LEAD和LAG函数,它们可以完全满足您的需要:将“leading”或“laging”行放入当前行。看看这是否有效(希望它至少能让你开始):
lag()
函数提供的功能是将当前行中的值与前一行中的值进行比较
在查询中尝试以下操作:
select...
tul_dtm_MoveInDate AS Move_In_Date,
tul_dtm_MoveOutDate AS Move_Out_Date,
DateDiff(day, Lag(tul_dtm_MoveOutDate,1) over(partition by uty_vch_Code, tul_int_FacilityId order by tul_dtm_MoveInDate), tul_dtm_MoveInDate) DaysVacant,
...
lag()
函数提供的功能是将当前行中的值与前一行中的值进行比较
在查询中尝试以下操作:
select...
tul_dtm_MoveInDate AS Move_In_Date,
tul_dtm_MoveOutDate AS Move_Out_Date,
DateDiff(day, Lag(tul_dtm_MoveOutDate,1) over(partition by uty_vch_Code, tul_int_FacilityId order by tul_dtm_MoveInDate), tul_dtm_MoveInDate) DaysVacant,
...
非常感谢你的帮助,这个社区很棒。我正在工作中学习SQL,没有人去问问题,所以这个平台是我唯一的生命线。当我运行您的查询时,上一个_时差列为每一行返回“2020-07-06”中相同的上一个时差,而不是每个时差的上一个时差。从我在网上读到的其他文章中也有类似的问题,也许RN函数在这里是关键?我不是专家。再次感谢,非常感谢您的帮助。@Casey,我编辑了SQL以避免空值或相等的移出日期。您可以在子选择中进一步使用连接以获得不同的结果。Lag和RowNumber更简单,工作也很好,但它们是MS-SQL特有的,所以您需要在其他数据库上学习其他内容。我总是先尝试用ANSI-SQL完成它,因为这些知识可以在许多其他DB引擎上使用。祝你好运非常感谢你的帮助,这个社区很棒。我正在工作中学习SQL,没有人去问问题,所以这个平台是我唯一的生命线。当我运行您的查询时,上一个_时差列为每一行返回“2020-07-06”中相同的上一个时差,而不是每个时差的上一个时差。从我在网上读到的其他文章中也有类似的问题,也许RN函数在这里是关键?我不是专家。再次感谢,非常感谢您的帮助。@Casey,我编辑了SQL以避免空值或相等的移出日期。您可以在子选择中进一步使用连接以获得不同的结果。Lag和RowNumber更简单,工作也很好,但它们是MS-SQL特定的,所以您需要