查找两个日期之间的元素并将它们分组

时间:2018-01-02 20:59:16

标签: php mysql sql

我有这张桌子:

___Bookings

|--------|------------|--------------|------------|------------|
| BOO_Id | BOO_RoomId | BOO_ClientId | BOO_DateCI | BOO_DateCO |
|--------|------------|--------------|------------|------------|
| 1      | 9          | 45           | 2018-01-02 | 2018-01-03 |
| 2      | 4          | 46           | 2017-12-30 | 2018-01-07 |
| 3      | 3          | 2            | 2018-12-31 | 2018-01-01 |
| 4      | 9          | 98           | 2018-01-05 | 2018-01-10 |
|--------|------------|--------------|------------|------------|

我希望每天在出发,抵达或内部展示预订。

所需的输出应该是这样的:

2017-12-30  =  Booking #2 in arrival.
2017-12-31  =  Booking #3 in arrival.
            =  Booking #1 in arrival.
            =  Booking #2 in house.
2018-01-01  =  Booking #3 in departure.
            =  Booking #2 in house.
2018-01-02  =  Booking #1 in arrival.
            =  Booking #2 in house.
2018-01-03  =  Booking #1 in departure.
            =  Booking #2 in house.
2018-01-04  =  Booking #2 in house.
2018-01-05  =  Booking #4 in arrival.
            =  Booking #2 in house.
2018-01-06  =  Booking #2 in house.
            =  Booking #4 in house.
2018-01-07  =  Booking #2 in departure.
            =  Booking #4 in house.
2018-01-08  =  Booking #4 in house.
2018-01-09  =  Booking #4 in house.
2018-01-10  =  Booking #4 in departure.

我已经尝试过:

SELECT *,
    CASE 
      WHEN BOO_DateCI = '2017-04-01' THEN 'In Arrival'
      WHEN BOO_DateCO = '2017-04-30' THEN 'In Departure'
      WHEN '2017-04-01' > BOO_DateCI AND '2017-04-01' < BOO_DateCO THEN 'In House'
    END
FROM ___Bookings
WHERE BOO_DateCI = '2017-04-01'
OR BOO_DateCO = '2017-04-30'
OR '2017-04-01' BETWEEN BOO_DateCI AND BOO_DateCO;

但我无法获得in house预订,并且无法根据状态arrivaldeparturein-house对预订进行分组。

1 个答案:

答案 0 :(得分:0)

您缺少的是一个天数列表,如果您在数据库中没有专用的日期维度,您可以像这样手动执行:

DECLARE @start DATE, @end DATE;
SELECT @start = '20171215', @end = '20180107';

;WITH n AS 
(
  SELECT TOP (DATEDIFF(DAY, @start, @end) + 1) 
   n = ROW_NUMBER() OVER (ORDER BY [object_id])
  FROM sys.all_objects
)
SELECT DATEADD(DAY, n-1, @start) as Date
into #Days
FROM n;

现在我们有一个日期列表,只需将您的列表加入日期列表即可。

select d.date
    , case when b.boo_id is null then 'No Bookings' else 'Booking #' + 
        cast(b.boo_id as varchar(255)) +
        ' In ' + case when b.boo_id is null then ''
            when d.date = b.BOO_DateCI then 'Checking In'
            when d.date = b.BOO_DateCO Then 'Checking Out'
            else 'In House' end as BookingStatus
from #Days d
  left outer join ___Bookings b
    on d.date between b.BOO_DateCI and b.BOO_DateCO

我们使用左外连接,以防有一天没有来宾,因为我们使用左,我们必须优雅地考虑空值,这是isnull和case语句的工作。其余的是一些演绎推理,date_CI可能是签到的,date_CO可能是Check out。希望有所帮助!