Làm thế nào có thể tìm thấy một value không tồn tại trong bảng?


0 Phiếu
Đã hỏi 24/5/2016 bởi Gur1443Of (49,540 điểm)
Tôi có một table đơn giản được gọi là Bookings có 2 cột BookDateBookSlot. BookDate cột sẽ có ngày chỉ (không có thời gian) và cột BookSlot sẽ có thời gian ngày trong khoảng thời gian 30 phút từ 0 đến 1410 bao gồm. (tức là 600 = 10:00 am) làm thế nào có thể tìm thấy các khe cắm đầu tiên có sẵn trong (chưa đặt) trong tương lai mà không cần chạy qua một vòng lặp? Dưới đây là các dữ liệu nào về định nghĩa và test table :
Create Table Bookings(
    BookDate DateTime Not Null,
    BookSlot Int Not Null
)
Go
Insert Into Bookings(BookDate,BookSlot) Values('2014-07-01',0);
Insert Into Bookings(BookDate,BookSlot) Values('2014-07-01',30);
Insert Into Bookings(BookDate,BookSlot) Values('2014-07-01',60);
Insert Into Bookings(BookDate,BookSlot) Values('2014-07-01',630);
Insert Into Bookings(BookDate,BookSlot) Values('2014-07-02',60);
Insert Into Bookings(BookDate,BookSlot) Values('2014-07-02',90);
Insert Into Bookings(BookDate,BookSlot) Values('2014-07-02',120);
tôi muốn có một cách để trở về các khe cắm có sẵn đầu tiên mà không phải là trong table và đó là trong tương lai (dựa trên thời gian server ). Dựa trên trên dữ liệu test :
  • nếu tất cả thời gian server tháng bảy 1, 00:10 am , kết quả nên là 1 tháng bảy, 90 phút (01:30 am).
  • nếu tất cả thời gian server là 2 tháng bảy, 01:05 am , kết quả nên là 2 tháng bảy, 150 phút (02:30 am).
nếu không có không có chỗ trong tương lai, function sẽ trở lại chỉ đơn giản là nửa giờ gần nhất trong tương lai. --SQL Fiddle cho điều này là ở đây:

5 Câu trả lời

0 Phiếu
Đã trả lời 02/6/2016 bởi Aprea_5139 (330 điểm)
Hãy thử này:
SELECT a.bookdate, ((a.bookslot/60.)+.5) * 60
FROM bookings a LEFT JOIN bookings b 
ON a.bookdate=b.bookdate AND (a.bookslot/60.)+.50=b.bookslot/60.
WHERE b.bookslot IS null
Đã bình luận 02/6/2016 bởi licea_in (440 điểm)
Giá trị chèn vào đặt chỗ (BookDate, BookSlot) (' 2014 -07-01', 630); Xin vui lòng giải thích Bookslot value của 630 và các giá trị tiếp theo...
Đã bình luận 04/6/2016 bởi Utilize (100 điểm)
OP đã giải thích những gì đã có, intervalled đại diện cho 30 phút số khe cắm như vậy nếu '600 '= 10:00 am rồi' 630' sẽ là 10:30 am
0 Phiếu
Đã trả lời 04/6/2016 bởi Gur6236lym (420 điểm)
Hãy thử này:
SELECT a.bookdate, ((a.bookslot/60.)+.5) * 60
FROM bookings a LEFT JOIN bookings b 
ON a.bookdate=b.bookdate AND (a.bookslot/60.)+.50=b.bookslot/60.
WHERE b.bookslot IS null
0 Phiếu
Đã trả lời 04/6/2016 bởi Provide (480 điểm)
Nó có một chút phức tạp, nhưng hãy thử này:
WITH DATA 
     AS (SELECT *, 
                Row_number() 
                  OVER ( 
                    ORDER BY BOOKDATE, BOOKSLOT) RN 
         FROM   BOOKINGS) 
SELECT CASE 
         WHEN T.BOOKSLOT = 1410 THEN Dateadd(DAY, 1, BOOKDATE) 
         ELSE BOOKDATE 
       END Book_Date, 
       CASE 
         WHEN T.BOOKSLOT = 1410 THEN 0 
         ELSE BOOKSLOT + 30 
       END Book_Slot 
FROM   (SELECT TOP 1 T1.* 
        FROM   DATA T1 
               LEFT JOIN DATA t2 
                      ON t1.RN = T2.RN - 1 
        WHERE  t2.BOOKSLOT - t1.BOOKSLOT > 30 
                OR ( t1.BOOKDATE != T2.BOOKDATE 
                     AND ( t2.BOOKSLOT != 0 
                            OR t1.BOOKSLOT != 630 ) ) 
                OR t2.BOOKSLOT IS NULL)T 
ở đây là ví dụ SQL fiddle. giải thích giải pháp này có 2 phần: so sánh mỗi dòng tiếp theo và kiểm tra đối với một khoảng cách (có thể được thực hiện dễ dàng hơn trong SQL 2012) thêm một nửa giờ để tạo ra các khe cắm tiếp theo, điều này có thể bao gồm di chuyển đến ngày hôm sau nếu cần thiết. chỉnh thêm TOP 1 trong query vì vậy mà chỉ có các khe cắm đầu tiên trở lại theo yêu cầu. Cập Nhật ở đây là phiên bản Cập Nhật, bao gồm cả 2 yếu tố mới (hiện hành ngày + thời gian nhận được và đối phó với bàn trống rỗng): DECLARE @Date DATETIME = '2014-07-01', @Slot INT = 630 DECLARE @time AS TIME = Cast(Getdate() AS TIME) SELECT @Slot = Datepart(HOUR, @time) * 60 + Round(Datepart(MINUTE, @time) / 30, 0) * 30 + 30 SET @Date = Cast(Getdate() AS DATE) ;WITH DATA AS (SELECT *, Row_number() OVER ( ORDER BY BOOKDATE, BOOKSLOT) RN FROM BOOKINGS WHERE BOOKDATE > @Date OR ( BOOKDATE = @Date AND BOOKSLOT >= @Slot )) SELECT TOP 1 BOOK_DATE, BOOK_SLOT FROM (SELECT CASE WHEN RN = 1 AND NOT (@slot = BOOKSLOT AND @Date = BOOKDATE) THEN @Date WHEN T.BOOKSLOT = 1410 THEN Dateadd(DAY, 1, BOOKDATE) ELSE BOOKDATE END Book_Date, CASE WHEN RN = 1 AND NOT (@slot = BOOKSLOT AND @Date = BOOKDATE) THEN @Slot WHEN T.BOOKSLOT = 1410 THEN 0 ELSE BOOKSLOT + 30 END Book_Slot, 1 AS ID FROM (SELECT TOP 1 T1.* FROM DATA T1 LEFT JOIN DATA t2 ON t1.RN = T2.RN - 1 WHERE t2.BOOKSLOT - t1.BOOKSLOT > 30 OR ( t1.BOOKDATE != T2.BOOKDATE AND ( t2.BOOKSLOT != 0 OR t1.BOOKSLOT != 1410 ) ) OR t2.BOOKSLOT IS NULL)T UNION SELECT @date AS bookDate, @slot AS BookSlot, 2 ID)X ORDER BY X.ID chơi xung quanh với SQL fiddle và cho tôi biết những gì bạn nghĩ.
0 Phiếu
Đã trả lời 04/6/2016 bởi Mealy_360 (240 điểm)
Nó có một chút phức tạp, nhưng hãy thử này:
WITH DATA 
     AS (SELECT *, 
                Row_number() 
                  OVER ( 
                    ORDER BY BOOKDATE, BOOKSLOT) RN 
         FROM   BOOKINGS) 
SELECT CASE 
         WHEN T.BOOKSLOT = 1410 THEN Dateadd(DAY, 1, BOOKDATE) 
         ELSE BOOKDATE 
       END Book_Date, 
       CASE 
         WHEN T.BOOKSLOT = 1410 THEN 0 
         ELSE BOOKSLOT + 30 
       END Book_Slot 
FROM   (SELECT TOP 1 T1.* 
        FROM   DATA T1 
               LEFT JOIN DATA t2 
                      ON t1.RN = T2.RN - 1 
        WHERE  t2.BOOKSLOT - t1.BOOKSLOT > 30 
                OR ( t1.BOOKDATE != T2.BOOKDATE 
                     AND ( t2.BOOKSLOT != 0 
                            OR t1.BOOKSLOT != 630 ) ) 
                OR t2.BOOKSLOT IS NULL)T 
ở đây là ví dụ SQL fiddle. giải thích giải pháp này có 2 phần: so sánh mỗi dòng tiếp theo và kiểm tra đối với một khoảng cách (có thể được thực hiện dễ dàng hơn trong SQL 2012) thêm một nửa giờ để tạo ra các khe cắm tiếp theo, điều này có thể bao gồm di chuyển đến ngày hôm sau nếu cần thiết. chỉnh thêm TOP 1 trong query vì vậy mà chỉ có các khe cắm đầu tiên trở lại theo yêu cầu. Cập Nhật ở đây là phiên bản Cập Nhật, bao gồm cả 2 yếu tố mới (hiện hành ngày + thời gian nhận được và đối phó với bàn trống rỗng): DECLARE @Date DATETIME = '2014-07-01', @Slot INT = 630 DECLARE @time AS TIME = Cast(Getdate() AS TIME) SELECT @Slot = Datepart(HOUR, @time) * 60 + Round(Datepart(MINUTE, @time) / 30, 0) * 30 + 30 SET @Date = Cast(Getdate() AS DATE) ;WITH DATA AS (SELECT *, Row_number() OVER ( ORDER BY BOOKDATE, BOOKSLOT) RN FROM BOOKINGS WHERE BOOKDATE > @Date OR ( BOOKDATE = @Date AND BOOKSLOT >= @Slot )) SELECT TOP 1 BOOK_DATE, BOOK_SLOT FROM (SELECT CASE WHEN RN = 1 AND NOT (@slot = BOOKSLOT AND @Date = BOOKDATE) THEN @Date WHEN T.BOOKSLOT = 1410 THEN Dateadd(DAY, 1, BOOKDATE) ELSE BOOKDATE END Book_Date, CASE WHEN RN = 1 AND NOT (@slot = BOOKSLOT AND @Date = BOOKDATE) THEN @Slot WHEN T.BOOKSLOT = 1410 THEN 0 ELSE BOOKSLOT + 30 END Book_Slot, 1 AS ID FROM (SELECT TOP 1 T1.* FROM DATA T1 LEFT JOIN DATA t2 ON t1.RN = T2.RN - 1 WHERE t2.BOOKSLOT - t1.BOOKSLOT > 30 OR ( t1.BOOKDATE != T2.BOOKDATE AND ( t2.BOOKSLOT != 0 OR t1.BOOKSLOT != 1410 ) ) OR t2.BOOKSLOT IS NULL)T UNION SELECT @date AS bookDate, @slot AS BookSlot, 2 ID)X ORDER BY X.ID chơi xung quanh với SQL fiddle và cho tôi biết những gì bạn nghĩ.
Đã bình luận 06/6/2016 bởi haveeska (100 điểm)
http://pastebin.com/ gKVFtkfW - ban đầu là một câu trả lời bởi vì nó sẽ không phù hợp trong một bình luận, nhưng điều này là tốt hơn. Có một số code có mà là một nửa con đường đó, nó chỉ chuyển đổi datetime tôi không chắc chắn của.
0 Phiếu
Đã trả lời 04/6/2016 bởi njr_And (360 điểm)
In SQL Server 2012 and later, you can use the lead() function. The logic is a bit convoluted because of all the boundary conditions. I think this captures it:
select top 1
       (case when BookSlot = 1410 then BookDate else BookDate + 1 end) as BookDate,
       (case when BookSlot = 1410 then 0 else BookSlot + 30 end) as BookSlot
from (select b.*,
             lead(BookDate) over (order by BookDate) as next_dt,
             lead(BookSlot) over (partition by BookDate order by BookSlot) as next_bs
      from bookings b
     ) b
where (next_bs is null and BookSlot < 1410 or
       next_bs - BookSlot > 30 or
       BookSlot = 1410 and (next_dt <> BookDate + 1 or next_dt = BookDate and next_bs <> 0)
      )
order by BookDate, BookSlot;
Đã bình luận 06/6/2016 bởi Ohg_8169_E (630 điểm)
, Xin vui lòng xem những lời giải thích ở trên. BookSlot là trong vài phút một ngày. 630 có nghĩa là 10:30 am. Chỉ chia cho 60 để có được thời gian.

ToughDev Q&A là gì?

Trang web hỏi đáp cho các bạn đam mê lập trình, phát triển phần mềm và các vấn đề kỹ thuật khác. Với sự giúp đỡ của bạn, chúng tôi hy vọng sẽ xây dựng thành công một thư viện đầy đủ các câu hỏi và trả lời về tất cả các vấn đề có liên quan đến lập trình!







...