복붙노트

[SQL] 시간 중복에 대한 테이블을 확인?

SQL

시간 중복에 대한 테이블을 확인?

나는 다음과 같은 필드가 MySQL의 테이블이 있습니다 :

STARTTIME 및 종료 시각은 MySQL의 TIME 필드 (하지 DATETIME)입니다. 나는 테이블에서 시간 범위의 모든 중복이 있는지 정기적으로 "스캔"테이블에 방법이 필요합니다. 10에서 00과 다른 : 00-11 : 30-11 : 10에서 이벤트가있는 경우 (30)가, 나는 시간의 중복의 존재의 경고가되고 싶어요.

아무것도 공상 정말 모든 I는 중복이 존재하는지 여부를 알고 싶어요.

나는 이것을 실행하기 위해 PHP를 사용하는거야.

해결법

  1. ==============================

    1.이것은 내가 몇 년 전에 답을 발견하는 쿼리 패턴입니다 :

    이것은 내가 몇 년 전에 답을 발견하는 쿼리 패턴입니다 :

    SELECT *
    FROM mytable a
    JOIN mytable b on a.starttime <= b.endtime
        and a.endtime >= b.starttime
        and a.name != b.name; -- ideally, this would compare a "key" column, eg id
    

    "어떤 중복"을 찾으려면, 당신은 서로와 기간의 반대 끝을 비교합니다. 그것은의 뭔가 내가 밖으로 펜과 종이를 얻고 가장자리의 경우는 이러한 비교에 아래로 삶은 것을 깨닫게 인접한 범위를 그릴 수 있었다.

    당신이 겹치지 행을 방지하려면, 트리거에서이 쿼리의 변형을 넣어 :

    create trigger mytable_no_overlap
    before insert on mytable
    for each row
    begin
      if exists (select * from mytable
                 where starttime <= new.endtime
                 and endtime >= new.starttime) then
        signal sqlstate '45000' SET MESSAGE_TEXT = 'Overlaps with existing data';
      end if;
    end;
    
  2. ==============================

    2.나는 일이 개 시간 범위가 겹치는 경우 확인하는 일반적인 기능을 원하는 것 또한 일정은 자정 전에 시작 및 종료 후, 같은 경우와 작업 "17 : 00 : 00-03 : 00 : 00"와 "14시 : 00-01 : 00 : I 보헤미안하여 용액을 개질되도록 00 "오버랩해야

    나는 일이 개 시간 범위가 겹치는 경우 확인하는 일반적인 기능을 원하는 것 또한 일정은 자정 전에 시작 및 종료 후, 같은 경우와 작업 "17 : 00 : 00-03 : 00 : 00"와 "14시 : 00-01 : 00 : I 보헤미안하여 용액을 개질되도록 00 "오버랩해야

    다음과 같이이 기능을 사용

    SELECT func_time_overlap("17:00:00","03:00:00", "14:00:00","01:00:00")
    

    또는이 같은 귀하의 경우

    SELECT *
    FROM mytable a
    JOIN mytable b ON (
        a.name != b.name 
        AND func_time_overlap(a.starttime, a.endtime, b.starttime, b.endtime)
    );
    

    여기서, 함수 정의는

    CREATE FUNCTION `func_time_overlap`(a_start TIME, a_end TIME, b_start TIME, b_end TIME) 
    RETURNS tinyint(1) 
    DETERMINISTIC
    BEGIN
    
    -- there are only two cases when they don't overlap, but a lot of possible cases where they do overlap
    
    -- There are two time formats, one is an interval of time that can go over 24 hours, the other is a daily time format that never goes above 24 hours
    -- by default mysql uses TIME as an interval
    -- this converts a TIME interval into a date time format
    
    -- I'm not using `TIME(CAST(a_start AS DATETIME));` to convert the time interval to a time
    -- because it uses the current day by default and might get affected by the timezone settings of the database, 
    -- just imagine the next day having the DST change.
    -- although the CAST should work fine if you use UTC
    
    IF a_start >= 24 THEN 
        SET a_start = TIME(CONCAT(MOD(HOUR(a_start), 24),':',MINUTE(a_start),':',SECOND(a_start))); 
    END IF;
    
    IF b_start >= 24 THEN 
        SET b_start = TIME(CONCAT(MOD(HOUR(b_start), 24),':',MINUTE(b_start),':',SECOND(b_start))); 
    END IF;
    
    IF a_end > 24 THEN 
        SET a_end = TIME(CONCAT(MOD(HOUR(a_end), 24),':',MINUTE(a_end),':',SECOND(a_end))); 
    END IF;
    
    IF b_end > 24 THEN 
        SET b_end = TIME(CONCAT(MOD(HOUR(b_end), 24),':',MINUTE(b_end),':',SECOND(b_end))); 
    END IF;
    
    
    -- if the time range passes the midnight mark, then add 24 hours to the time
    IF a_start >= a_end THEN 
        SET a_end = a_end + INTERVAL 24 HOUR; 
    END IF;
    
    IF b_start >= b_end THEN 
        SET b_end = b_end + INTERVAL 24 HOUR; 
    END IF;
    
    RETURN a_start < b_end AND a_end > b_start;
    
    
    END
    

    나는 시간을 (CAST (AS DATETIME a_start)) 사용하지 않는; 그것은 기본적으로 현재 날짜를 사용하여 데이터베이스의 시간대 설정의 영향을받을 수 있기 때문에 시간에 시간 간격을 변환, 바로 DST 변화를 갖는 다음날 상상한다.

    데이터베이스는 UTC 시간대 (예상대로)를 사용하는 경우에 당신은이를 사용할 수 있습니다

    IF a_start >= 24 THEN 
        SET a_start = TIME(CAST(a_start AS DATETIME)); 
    END IF;
    
    IF b_start >= 24 THEN 
        SET b_start = TIME(CAST(b_start AS DATETIME)); 
    END IF;
    
    IF a_end > 24 THEN 
        SET a_end = TIME(CAST(a_end AS DATETIME));
    END IF;
    
    IF b_end > 24 THEN 
        SET b_end = TIME(CAST(b_end AS DATETIME));
    END IF;
    
  3. ==============================

    3.이 시도:

    이 시도:

    declare @tempTbl table(RecID)
    
        insert into @tempTbl
        Select RecID
        from 
        (
        Select t.RecID from Table1 t,Table1 t1
        where t.StartTime between t1.StartTime AND t1.EndTime
        AND t.RecID <> t1.RecID  
    
        )
    
  4. ==============================

    4.그것은 나를 위해 작동이 시도

    그것은 나를 위해 작동이 시도

    SELECT * from Shedulles a 
    where exists 
    ( select 1 from Shedulles b 
        where 
        a.ShedulleId != b.ShedulleId 
        and ( a.DateFrom between b.DateFrom and b.DateTo 
        or a.DateTo between b.DateFrom and b.DateTo 
        or b.DateFrom between a.DateFrom and a.DateTo ) 
        and a.DateFrom != b.DateTo 
        and b.DateFrom != a.DateTo 
    );
    

    또는이 하나

    SELECT DISTINCT a.* FROM Shedulles a
    JOIN Shedulles b 
        ON 
        a.ShedulleId != b.ShedulleId 
        and ( a.DateFrom between b.DateFrom and b.DateTo 
        or a.DateTo between b.DateFrom and b.DateTo 
        or b.DateFrom between a.DateFrom and a.DateTo ) 
        and a.DateFrom != b.DateTo 
        and b.DateFrom != a.DateTo 
    
  5. from https://stackoverflow.com/questions/6571538/checking-a-table-for-time-overlap by cc-by-sa and MIT license