重复ID基于

时间:2018-02-02 15:48:59

标签: sql sql-server tsql sql-server-2014

我有一个非常简单的要求,但我很难找到解决方法。

我有一个非常简单的查询:

SELECT
  ServiceCode,
  StartDate,
  Available,
  Nights,
  BookingID
FROM @tmpAvailability
LEFT JOIN vwRSBooking B 
  ON B.Depart = A.StartDate 
 AND B.ServiceCode = A.SupplierCode 
 AND B.StatusID IN (2640, 2621)
ORDER BY StartDate;

由2张桌子组成 @tmpAvailability由以下字段组成:

  • SupplierCode
  • 开始日期
  • 可用

vwRSBooking,包含以下字段

  • BookingID
  • DepartDate
  • StatusID

离开和开始日期可以加入第一天的链接,并且可以加入服务代码和供应商代码,以确保可用性链接到同一供应商。

产生如下输出:

Code    |    Dates    |    Available  |  Nights | BookingID
TEST    | 2018-01-04  |        1      |  NULL   | NULL
TEST    | 2018-01-05  |        1      |  NULL   | NULL
TEST    | 2018-01-06  |        0      |  4      | 123456
TEST    | 2018-01-07  |        0      |  NULL   | NULL
TEST    | 2018-01-08  |        0      |  NULL   | NULL
TEST    | 2018-01-09  |        0      |  NULL   | NULL
TEST    | 2018-01-10  |        1      |  NULL   | NULL
TEST    | 2018-01-11  |        1      |  NULL   | NULL
TEST    | 2018-01-12  |        1      |  NULL   | NULL
TEST    | 2018-01-13  |        0      |  NULL   | 234567
TEST    | 2018-01-14  |        0      |  NULL   | NULL
TEST    | 2018-01-15  |        0      |  NULL   | NULL

我需要的是,当BookingID在4天内预订ID和夜晚分布在那些日子时,例如:

Code    |    Dates    |    Available  |  Nights | BookingID
TEST    | 2018-01-04  |        1      |  NULL   | NULL
TEST    | 2018-01-05  |        1      |  NULL   | NULL
TEST    | 2018-01-06  |        0      |  4      | 123456
TEST    | 2018-01-07  |        0      |  4      | 123456
TEST    | 2018-01-08  |        0      |  4      | 123456
TEST    | 2018-01-09  |        0      |  4      | 123456
TEST    | 2018-01-10  |        1      |  NULL   | NULL
TEST    | 2018-01-11  |        1      |  NULL   | NULL
TEST    | 2018-01-12  |        1      |  NULL   | NULL
TEST    | 2018-01-13  |        0      |  3      | 234567
TEST    | 2018-01-14  |        0      |  3      | 234567
TEST    | 2018-01-15  |        0      |  3      | 234567
TEST    | 2018-01-16  |        1      |  NULL   | NULL

如果有人对如何解决这个问题有任何想法,那将非常感激。

安德鲁

2 个答案:

答案 0 :(得分:1)

您需要一张日历表,其中包含您日期可能属于的日期范围内的所有日期。对于这个例子,我在2018年1月构建了一个。然后我们可以加入这个表来创建额外的行。

以下是我使用的示例代码。你可以在SQL Fiddle看到它。

CREATE TABLE code (
  code varchar(max),
  dates date,
  available int,
  nights int,
  bookingid int
  )

INSERT INTO code VALUES
('TEST','2018-01-04','1',NULL,NULL),
('TEST','2018-01-05','1',NULL,NULL),
('TEST','2018-01-06','0',4,123456),
('TEST','2018-01-07','0',NULL,NULL),
('TEST','2018-01-08','0',NULL,NULL),
('TEST','2018-01-09','0',NULL,NULL),
('TEST','2018-01-10','1',NULL,NULL),
('TEST','2018-01-11','1',NULL,NULL),
('TEST','2018-01-12','1',NULL,NULL),
('TEST','2018-01-13','0',3,234567),
('TEST','2018-01-14','0',NULL,NULL),
('TEST','2018-01-15','0',NULL,NULL)

CREATE TABLE dates (
  dates date
  )
INSERT INTO dates VALUES
('2018-01-01'),('2018-01-02'),('2018-01-03'),('2018-01-04'),('2018-01-05'),('2018-01-06'),('2018-01-07'),('2018-01-08'),('2018-01-09'),('2018-01-10'),('2018-01-11'),('2018-01-12'),('2018-01-13'),('2018-01-14'),('2018-01-15'),('2018-01-16'),('2018-01-17'),('2018-01-18'),('2018-01-19'),('2018-01-20'),('2018-01-21'),('2018-01-22'),('2018-01-23'),('2018-01-24'),('2018-01-25'),('2018-01-26'),('2018-01-27'),('2018-01-28'),('2018-01-29'),('2018-01-30'),('2018-01-31')

以下是基于此数据集的查询:

SELECT
  code.code,
  dates.dates,
  code.available,
  code.nights,
  code.bookingid
FROM code
LEFT JOIN dates ON
  dates.dates >= code.dates
  AND dates.dates < DATEADD(DAY,nights,code.dates)

编辑:这是一个使用您的初始查询作为子查询的示例,如果您想要一个副本和一个副本,将结果集加入日期表。糊。仍然需要创建日期表。

SELECT
  ServiceCode,
  StartDate,
  Available,
  Nights,
  BookingID
FROM (
  SELECT
    ServiceCode,
    StartDate,
    Available,
    Nights,
    BookingID
  FROM @tmpAvailability
  LEFT JOIN vwRSBooking B 
    ON B.Depart = A.StartDate 
    AND B.ServiceCode = A.SupplierCode 
    AND B.StatusID IN (2640, 2621)
  ) code
LEFT JOIN dates ON
  dates.dates >= code.dates
  AND dates.dates < DATEADD(DAY,nights,code.dates)
ORDER BY StartDate;

答案 1 :(得分:1)

您可以将vwRSBooking替换为使用CTE的其他视图,以获取预订涵盖的所有日期。然后使用视图的coverdate加入@tmpAvailability表:

CREATE VIEW vwRSBookingFull
AS
    WITH cte ( bookingid, nights, depart, code, coverdate)
         AS (SELECT bookingid,
                    nights,
                    depart,
                    code,
                    depart
               FROM vwRSBooking

             UNION ALL
             SELECT c.bookingid,
                    c.nights,
                    c.depart,
                    c.code,
                    DATEADD(d, 1, c.coverdate)
               FROM cte c
              WHERE DATEDIFF(d, c.depart, c.coverdate) < (c.nights - 1))
    SELECT c.bookingid,
           c.nights,
           c.depart,
           c.code,
           c.coverdate
      FROM cte c

GO