如何检索涵盖日期范围内所有日期的记录?

时间:2018-03-12 20:32:06

标签: sql sql-server stored-procedures sql-server-2014 where-clause

想象一下,您有类似行动租赁或酒店场景的情况,其中一个单位可以在特定日期内获得费率,并且可以提供或不提供。我希望能够搜索我所有单位的指定到达日期和出发日期,只能带回符合整个时间段的单位。

让我们说每个单位都有一个类似于下面的费率表

PropertyID    Rate    Start_Date    End_Date   Status    Type
1             400     03/12/18      03/13/18   Available Daily
1             400     03/13/18      03/14/18   Available Daily
1             400     03/14/18      03/15/18   Available Daily
1             400     03/15/18      03/16/18   Reserved  Daily
1             400     03/16/18      03/17/18   Available Daily
1             400     03/17/18      03/18/18   Available Daily
1             400     03/18/18      03/19/18   Available Daily
1             900     03/12/18      03/19/18   Blocked   Weekly

每日费率分为每天,因为您可以随时预订一天,而每周费率则需要全额费用。在上述情况下,事实证明我无法租用每周费率,因为15天是保留的,这是每周费率的一部分。

如果有人要搜索他们想要留在3月12日到18/19/19并且假设以上所有内容都可用,我会在商店程序中做到这一点(伪代码)

Select stuff
From Property
Inner Join PropertyRate pr
where pr.Start_Date = @arrrivalDate And pr.End_Date = @departureDate

这会让我回到房产,因为每周房价适合。但是,如果每周费率被移除并且只是每日费率,则不会返回此属性。假设所有状态都可用于每日费率,此属性应返回,因为指定期间的每一天都可用。

如何检查所请求日期范围内的每一天是否有该时间段的可用日期?

如果重要,那就是Microsoft SQL Server 2014。

修改1:

要求提供表格定义。这是属性费率表创建脚本:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[PropertyRates]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[PropertyRates](
    [property_rate_id] [int] IDENTITY(1,1) NOT NULL,
    [rate_details_id] [int] NOT NULL,
    [property_id] [int] NOT NULL,
    [rate] [money] NOT NULL,
    [start_date] [date] NOT NULL,
    [end_date] [date] NOT NULL,
    [status] [varchar](20) NOT NULL,
    [created] [datetime] NOT NULL,  
 CONSTRAINT [PK_PropertyRates] PRIMARY KEY CLUSTERED 
(
    [property_rate_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

SET ANSI_PADDING OFF
GO

我相信这就是所要求的。

编辑2:

我不太清楚我要为输出做些什么。由于此SQL用于搜索功能,我只想返回属性的SINGLE属性记录,如果它在传入的搜索范围的每一天都有可用的费率。因此,如果该属性的许多费率可用,那么结束SQL应该只有属性记录,并覆盖传递日期范围内的每一天。

另请注意,除了每日和每周费率外,还有其他诸如每月,每月,每日2天等,但它们都填写了开始日期和结束日期列。

所以对于上面的例子,对于从3月12日到3月19日的住宿,我不应该取回房产,因为没有可用的天数范围,因为每周房价被阻止且每日房价有一个保留在中间。如果保留费率更改为可用,则应返回该属性。

2 个答案:

答案 0 :(得分:0)

select propertyid,count(*) 
from property 
where count(*) = datediff(dd,@startenddate, @enddate)+1 
and status='Available'
    group by propertyid

这将计算请求的天数(datediff)并计算表格中是否有可用的天数。

答案 1 :(得分:0)

UNION ALL可能是解决此问题的好方法:

DECLARE @ArrivalDate Date = '20180312'
DECLARE @DepartureDate Date = '20180319'

SELECT *
FROM myTable t1
JOIN (SELECT PropertyID, Type --Handle Weekly Availability
      FROM myTable
      WHERE Type = 'Weekly'
      AND Status = 'Available'
      AND Start_Date = @ArrivalDate
      AND End_Date = @DepartureDate
         UNION ALL
      SELECT PropertyID, Type --Handle Daily Availability
      FROM myTable
      WHERE Type = 'Daily'
      AND Status = 'Available'
      AND Start_Date >= @ArrivalDate
      AND End_Date <= @DepartureDate
      GROUP BY PropertyID, Type
      HAVING COUNT(DISTINCT Start_Date) = DATEDIFF(Day, @ArrivalDate, @DepartureDate)
    ) t2 ON t1.PropertyID = t2.PropertyID --JOIN back to retrieve other needed data
        AND t1.Type = t2.Type

Fiddle example here

注意,我将示例数据更改为每日一个有效和每周一个有效示例。