允许基于预订-SQL更新的方案

时间:2016-06-29 04:27:17

标签: sql oracle plsql oracle11g

方案是DEMO001系统由用户在8月10日至11月8日预订。

START_DATE     END DATE    SYSTEM
2016-08-10     2016-08-11  DEMO001
2016-09-05     2016-09-08  DEMO001
2016-08-08     2016-08-11  DEMO013
2016-08-16     2016-08-18  DEMO017

说我是否得到输入参数

1) start date as 2016-08-08  and end date as 2016-08-11 I can allow 
2) start date as 2016-08-11  and end date as 2016-09-08 I cannot allow
3) start date as 2016-08-10   and end date as 2016-08-15 I can allow
3) start date as 2016-08-10   and end date as 2016-09-06 I cannot allow

如果用户尝试通过延长或推迟开始日期或结束日期来更新任何此系统,如果在这些天之间没有其他人预订,我将不得不说0或1。

这是此方案的扩展

Checking if the "system" falls between two dates in SQL

我尝试修改它给出的建议,但无法正确使用它。请建议。

5 个答案:

答案 0 :(得分:4)

尝试:

WITH dates AS (

  -- input data (ranges)
  SELECT date '2016-08-08' as start_date,  date '2016-08-11' as end_date from dual union all
  SELECT date '2016-08-11',  date '2016-09-08' from dual union all
  SELECT date '2016-08-10',  date '2016-08-15' from dual union all
  SELECT date '2016-08-10',  date '2016-09-06' from dual
)

-- the query
SELECT d.start_date, d.end_date, 
       CASE WHEN count(*) > 1 
            THEN 'Disallow' ELSE 'Allow' 
            -- change the above line to => THEN 0 ELSE 1 <= if you prefer numbers
       END is_allowed
FROM dates d
LEFT JOIN table1 t1 -- table1 holds booking data, eg DEMO0001 etc.
ON (d.Start_date <= t1.end_date)  and  (d.end_date >= t1.start_date ) 
    AND t1.system = 'DEMO001'
GROUP BY d.start_date, d.end_date
ORDER BY 1

答案 1 :(得分:2)

如果我正确理解您的问题,您正在寻找一种通用的解决方案来区分资源的时间段是否会及时重叠。

假设前四个示例行是名为BOOKING的表中的列,并且您想测试第一个预订的新日期,则可以使用以下查询执行此操作:

<%= form_tag(admin_orders_path, method: :get) %>

当然,CASE声明就是为了让测试结果在视觉上清晰明了。如果您希望0和1表示相反的结果,只需将其设为&#34; NOT EXIST&#34;

答案 2 :(得分:2)

根据我的理解,只有在没有其他日期的冲突时,您才需要更新系统的现有预订日期。

请尝试下面的代码,可能适用于您。

    CREATE TABLE bookings (BookingId INT IDENTITY(1,1), StartDate Date, EndDate DATE, [SYSTEM] varchar(64));

    INSERT INTO bookings (StartDate, EndDate, [SYSTEM])
    VALUES
        ('2016-08-10', '2016-08-11', 'DEMO001'),
        ('2016-09-05', '2016-09-08', 'DEMO001'),
        ('2016-08-08', '2016-08-11', 'DEMO013'),
        ('2016-08-16', '2016-08-18', 'DEMO017');

Booking Table

    DECLARE 
        @ExistingBookingId INT = 1
        ,@NewStartDate DATE = '2016-08-10'
        ,@NewEndDate DATE = '2016-09-06';

    DECLARE @SystemCorrespondingToBookingId VARCHAR(64);

    SELECT @SystemCorrespondingToBookingId = [System]
    FROM bookings
    WHERE bookingId = @ExistingBookingId

    ;WITH AnotherBookingDatesOfSystem (StartDt, EndDt)
    AS
    (
        SELECT StartDate, EndDate
        FROM Bookings
        WHERE [System] = @SystemCorrespondingToBookingId
            AND BookingId <> @ExistingBookingId
    )

    SELECT ISNULL(MIN(
             CASE
             WHEN @NewEndDate < StartDt OR @NewStartDate > EndDt
             THEN 1
             ELSE 0
             END
           ), 1) AS can_book
    FROM  AnotherBookingDatesOfSystem

适用于所有特定场景。

答案 3 :(得分:2)

完全归功于@kordirko,但只是为了让您了解熟悉的输出模型(由@MTO提供)

预订表:

CREATE TABLE table_name ( START_DATE, END_DATE, SYSTEMS ) AS
SELECT DATE '2016-08-10', DATE '2016-08-11', 'DEMO001' FROM DUAL UNION ALL
SELECT DATE '2016-09-05', DATE '2016-09-08', 'DEMO001' FROM DUAL UNION ALL
SELECT DATE '2016-08-08', DATE '2016-08-11', 'DEMO013' FROM DUAL UNION ALL
SELECT DATE '2016-08-16', DATE '2016-08-18', 'DEMO017' FROM DUAL;

使用绑定变量系统查询,start_date,end_date

SELECT :systems, :start_date, :end_date, 
       CASE WHEN COUNT(*) > 1 
            THEN 'I cannot Allow' ELSE 'I can Allow' 
        END result
FROM bookings t1 
WHERE ( :start_date <= t1.end_date) AND (:end_date >= t1.start_date ) 
    AND t1.systems = :systems
GROUP BY :start_date, :end_date;

输出:

1) DEMO001  2016-08-08  2016-08-11  -> I can Allow
2) DEMO001  2016-08-11  2016-09-08  -> I cannot Allow
3) DEMO001  2016-08-10  2016-08-15  -> I can Allow
4) DEMO001  2016-08-10  2016-09-06  -> I cannot Allow

答案 4 :(得分:1)

你可以根据OP链接中提到的sql语句尝试这个:

SELECT system, min(can_book) can_book
FROM (
       SELECT system,
         CASE
         WHEN (NOT(start_date BETWEEN :start_Date AND :end_date) 
               AND NOT(end_date BETWEEN :start_Date AND :end_date)) 
         THEN 1
         ELSE 0
         END
       ) AS can_book
FROM   table_name
)GROUP BY system;