sourcecode

SQL Infinite Calendar Pattern

copyscript 2023. 10. 11. 20:54
반응형

SQL Infinite Calendar Pattern

I'm going to make a Mysql based calendar system where you can have repeating pattern for lets say every monday forever and ever. It must also cover static/once-only events. What I'm wondering about, is which solution would be most logical (and best) for me to use. I have four methods which I'm wondering to chose between.

Method #1

매개변수를 허용하는 함수를 만듭니다.from그리고.to. 이 함수는 기존 정적 스케줄을 다음을 통해 가져오는 임시 테이블 테이블을 만듭니다.INSERT ... SELECT. 그 후 패턴 테이블을 읽고 다음을 기준으로 페로이드를 통해 임시 테이블을 채웁니다.from그리고.to.

This solution seems nice from the point of view that queries will be simplier to fetch data with and it works into infinity since you can just repopulate the table depending of which month you're loading. What I'm curious about is whenever this might be a laggy way to do it or not.

Method #2

서브쿼리를 통해 주어진 패턴을 생성하고 결합합니다.JOIN정적인 달력으로

This seems to be rather annoying since the queries would be a lot more bigger and would probably not be good at all(?).

Method #3

기본적으로 그냥INSERT1년 앞으로 말할 수 있는 패턴.그렇다면 크론 직업은 항상 1년 먼저 성공하기 위해 사람들이 다시 몰릴 것 같네요.

This is a simple way to do it, but it feels like a lot of unneeded data stored and it doesn't really give the infinity which I'm after.

Method #4 (Suggested by Veger)

If I understand correctly, this method would fetch the pattern from another query and creates events upon execution. It's similar to my thoughts regarding Method #1 in that way that I consider simple pattern to create several rows.

However if this would be implemented outside Mysql, I would loose some database functionality which I'm after.


I hope you guys understood my situation, and if you could suggest either given and argue why it's the best or give another solution.

Personally I like the Method #1 the most, but I'm curious if it's laggy to repopulate the calendar table each and every call.

저는 이런 달력을 만든 적이 있습니다.가장 좋은 방법은 크론이 예정된 방식으로 접근하는 것입니다.데이터베이스에서 분, 시간, 월, 월, 월, 일을 나타내는 필드를 만듭니다.

6월과 8월 매주 금요일 오후 10시에 열리는 행사에서 당신의 출품작은 다음과 같습니다.

Minute  Hour  DayOfMonth  Month  DayOfWeek
 0       22     *          6,8       5

그러면 이 정보를 무시하고 시작 날짜와 기간만 사용하는 일회성 이벤트로 플래그를 지정하는 필드를 가질 수 있습니다.최종적으로 이 종료를 반복하는 이벤트의 경우(3개월 동안 매주 주말이라고 함) 종료 날짜 필드만 추가하면 됩니다.

이렇게 하면 쉽게 다시 선택할 수 있고 저장해야 하는 데이터의 양을 줄일 수 있습니다.이를 통해 질의 또한 간소화됩니다.

임시 테이블을 만들 필요는 없다고 생각합니다.관련 이벤트를 다시 선택하려면 일정관리 보기에서 해당 이벤트를 선택합니다.달력 보기가 월 단위인 경우 선택한 내용은 다음과 같습니다.

SELECT Events.* 
FROM Events 
WHERE (Month LIKE '%,'.$current_month.',%' OR Month = '*') 
    AND DATE(StartDate) >= "'.date('Y-m-d', $firstDayOfCurrentMonth).'" 
    AND DATE(EndDate) <= "'.date('Y-m-d', $lastDayOfCurrentMonth).'"

분명히 이것은 준비된 성명서에 있어야 합니다.또한 쉼표로 구분된 월 목록(즉, 쉼표로 구분된 월 목록)의 첫 번째 값과 마지막 값 앞과 뒤에 쉼표가 있다고 가정합니다.,2,4,6, 를.Month당신이 원한다면 테이블과 둘사이의 결합 테이블.나머지는 달력을 렌더링할 때 php로 파싱할 수 있습니다.

일정관리의 주간 보기를 표시할 경우 다음과 같은 방법으로 선택할 수 있습니다.

SELECT Events.* 
FROM Events 
WHERE (DayOfMonth IN ('.implode(',', $days_this_week).','*') 
    AND (Month LIKE '%,'.$current_month.',%' OR Month = '*')) 
    AND DATE(StartDate) >= "'.date('Y-m-d', $firstDayOfCurrentMonth).'" 
    AND DATE(EndDate) <= "'.date('Y-m-d', $lastDayOfCurrentMonth).'"

저는 그 질문들을 테스트해보지 않았기 때문에 아마도 엉망인 괄호 같은 것들이 있을 것입니다.하지만 그것이 일반적인 생각일 것입니다.

따라서 표시 중인 각 요일에 대해 선택을 실행하거나 보기(월, 주 등)에 대한 모든 항목을 뒤로 선택하고 각 요일에 대한 이벤트를 루프오버할 수 있습니다.

저는 비거의 솔루션이 가장 좋습니다. 을 채우는 .여러 행을 채우는 대신 패턴만 채울 수 있습니다.합니다.crontab포맷.. 합니다.어쨌든 잘 작동합니다.

특정 고객이 일정관리를 로드하고 패턴을 기준으로 이벤트를 입력할 때 해당 고객에 대한 모든 패턴을 쿼리할 수 있습니다.단일 사용자를 위한 수천 개의 패턴을 가지고 있지 않다면, 이는 그렇게 느려서는 안 됩니다.또한 많은 수의 행 이벤트를 장기간 저장하는 것보다 빠릅니다.한 번에 모든 패턴을 선택하고 전처리를 해야 할 텐데, 한 번 더 말씀드리면 사용자당 패턴 수는 얼마나 될까요?1,000개 정도라도 꽤 빠를 겁니다.

GW Basic ;-)에서 아직 프로그래밍을 하고 있을 때부터 이런 생각이 있었는데 그때는 옵션 #3을 선택했는데 그게 다였습니다.그것을 돌이켜보면, 그리고 다른 몇몇 응답들도, 이것이 저의 현재 해결책이 될 것입니다.

테이블 구조

start (datetime)
stop (datetime, nullable)
interval_unit ([hour, day, week, month, year?])
interval_every (1 = every <unit>, 2 every two <units>, etc.)
type ([positive (default), negative]) - will explain later

옵션 필드:

title
duration

type 처리 field합니다.

  1. 긍정적인; 정상적인 치료, 그것은 달력에 나타납니다.
  2. negative; 이 이벤트는 다른 이벤트를 취소합니다(예: 14일이 아닌 매주 월요일).

도우미 쿼리

이 쿼리는 다음을 표시할 이벤트를 좁힙니다.

SELECT * FROM `events`
WHERE `start` >= :start AND (`stop` IS NULL OR `stop` < :stop)

할 때,은 다음과 같습니다.:stop범위보다 하루 앞서야 합니다

이제 여러분이 다루고자 하는 다양한 이벤트를 준비하겠습니다.

단일종목

start = '2012-06-15 09:00:00'
stop = '2012-06-15 09:00:00'
type = 'positive'

행사는 2012-06-15일 오전 9시 1회 개최

유계 반복 사건

start = '2012-06-15 05:00:00'
interval_unit = 'day'
interval_every = 1
stop = '2012-06-22 05:00:00'
type = 'positive'

2012-06-15일을 시작으로 매일 오전 5시에 행사가 열리며, 마지막 행사는 22일입니다.

무한 반복 이벤트

start = '2012-06-15 13:00:00'
interval_unit = 'week'
interval_every = 2
stop = null
type = 'positive'

2012-06-15부터 2주에 한 번씩 오후 1시에 행사가 열립니다.

예외가 있는 반복 이벤트

start = '2012-06-15 16:00:00'
interval_unit = 'week'
interval_every = 1
type = 'positive'
stop = null

start = '2012-06-22 16:00:00'
type = 'negative'
stop = '2012-06-22 16:00:00'

행사는 2012-06-22일부터 매주 오후 4시에 열리지만 22일에는 열리지 않습니다.

나는 이것의 행을 중심으로 다음과 같이 제안하고 싶습니다. 이벤트 테이블을 두 개로 나누십시오. 왜냐하면 분명히 두 가지 유형의 반복 이벤트와 정적 이벤트가 있고 유형에 따라 서로 다른 속성을 가질 것이기 때문입니다.

그런 다음 주어진 이벤트 검색에 대해 각 이벤트 유형에 대해 하나씩 두 개의 쿼리를 실행합니다.정적 이벤트 테이블의 경우 주어진 한 달 동안의 룩업이 조건(여기서 event_date > FirstDayOf)에서 해당 필드를 간단히 사용할 수 있도록 적어도 하나의 datetime 필드가 도전적으로 필요합니다.The Month and event_date < LastDayOfThe Month ).주별/년별 보기에 동일한 논리입니다.

이 결과 집합은 반복 이벤트 테이블의 두 번째 결과 집합과 결합됩니다.가능한 특성은 요일/월일을 주요 변수 2개로 사용하여 크론탭 항목과 유사할 수 있습니다.월간 조회 수를 보고 계신다면,

select * from recurring_events where DayOfWeek in (1,2,3,4,5,6,7) or (DayOfMonth > 0 and DayOfMonth < @NumberOfDaysInThisMonth )

주간/연간 보기의 경우에도 유사합니다.이것을 더 간단하게 인터페이스할 수 있도록 '날짜 A와 날짜 B 사이에 어떤 요일이 있는지'를 결정하기 위한 모든 논리와 함께 저장 프로시저를 사용합니다.

두 결과 세트가 모두 있으면 클라이언트에서 이를 함께 집계한 다음 함께 표시할 수 있습니다.이에 대한 장점은 "모의/빈 레코드"나 미리 채우는 비동기식 작업이 필요 없다는 것입니다. 쿼리는 즉시 쉽게 발생할 수 있으며 실제로 성능이 저하되는 경우 캐싱 계층을 추가해야 하며, 특히 이러한 특성의 시스템에서는 캐시가 완벽하게 합리적입니다.

저는 실제로 이와 유사한 것을 찾고 있으며 지금까지 (아직 구조화나 코드화를 시작하지 않은 서류상) 2개의 테이블에 있는 스토어를 찾고 있습니다.

  1. "이벤트"는 첫 번째 발생 날짜, 제목 및 설명(그리고 자동 증가 ID)을 가져옵니다.

  2. events_recursion 테이블은 (예를 들어 event_id 필드와 함께) 이전 테이블과 교차 참조되며 두 가지 가능한 방식으로 작동할 수 있습니다.

    2.A: 날짜별로 모든 발생 항목 저장(즉, 발생 시마다 1개의 항목이 있으므로 '이달의 매주 금요일'을 저장하려면 4개, '2012년의 매월 1일'을 저장하려면 12개)

    2.B: 또는 필드의 첫 번째 이벤트 발생일로부터 간격을 저장(초 단위로 저장) + 다른 필드의 마지막 발생일(또는 재귀 종료일)

ID : 2 EVENT_ID: 1 INTERVANT : 604800 (잘못하지 않았다면 일주일) END : 1356912000 (올해 말이어야 함)

그런 다음 일정을 보여주는 php를 열면 두 테이블 사이의 조인트로 해당 달에 아직 활성화된 이벤트를 확인할 수 있습니다.

하나의 테이블에 모두 저장하는 대신 2개의 테이블을 상호 참조하여 사용하는 이유는 프로젝트에서 "매주 금요일 및 매월 셋째 월요일"과 같은 매우 미친 이벤트가 표시된다는 사실 때문입니다(이 경우 이벤트 테이블에는 1개의 항목이 있고 두 번째 테이블에는 동일한 "event_id" 필드가 있는 2개가 표시됩니다).그건 그렇고, 제 프로젝트는 음악 선생님들을 위한 것인데, 한 번에 3개월 또는 6개월씩 엄격한 일정으로 결정된 작은 일들이 있고 정말 엉망진창입니다.)

하지만 제가 말씀드린 것처럼 아직 시작하지 않았기 때문에 귀사의 해결책을 기대하고 있습니다.

추신: 제 영어를 용서해주세요(그리고 잊어주세요), 첫째는 제 언어가 아니고 둘째는 꽤 늦은 밤이고 졸립니다.

MySQL Events에서 멋진 아이디어를 확인해 볼 수 있습니다.

기타 항목:
phpm마스터--작업- http:// ?utm_source rss&utm_ rss&utm_phpm-- -

http://dev.mysql.com/doc/refman/5.5/en/create-event.html

최상의 솔루션은 표준 준수(RFC5545)를 선호할 것인지 MySQL 내에서만 작동할 것인지에 따라 달라집니다.

반복 규칙 엔진이 필요한 유연성에 따라 달라질 수 있습니다.간단한 규칙(매월 1일 또는 매 1월)을 원한다면 위에서 제공하는 솔루션에 대해 상세히 설명했습니다.

그러나 캘린더 앱을 구축할 때 이 SO 게시물을 확인해야 하는 훨씬 더 복잡한 규칙을 포함하는 기존 표준(RFC5545)과의 호환성을 애플리케이션에서 제공하도록 해야 합니까? 날짜 또는 재발 규칙을 데이터베이스에 저장해야 합니까?

여기서 설명한 대로 하겠습니다.무한 캘린더를 생성합니다.

PHP/MySQL: 데이터베이스의 반복 이벤트를 모델로 하되 날짜 범위를 쿼리합니다.

단점은 질의하는 동안 계산이 좀 있을 것이라는 것입니다.고성능 웹사이트가 필요하다면 데이터를 미리 로딩하는 것이 방법입니다.캘린더에 있는 모든 이벤트를 미리 로드할 필요도 없어 한 이벤트에서 값을 쉽게 변경할 수 있습니다.하지만 지금부터 ...까지 모든 날짜를 저장하는 것이 현명할 것입니다.

이제 캐시된 값을 사용하면 무한 확장성은 떨어지지만 속도는 향상됩니다.

쉽게 접근할 수 있도록 owner의 복사본:

는 입니다라는 단할 것입니다.id그 표를 0부터 500까지의 숫자로 채웁니다.이제 우리는 이를 사용하여 일시적 루프를 사용하는 대신 선택을 쉽게 할 수 있습니다.

Id
-------------------------------------
0
1
2
etc...

그럼 이벤트를 다음과 같은 테이블에 저장해 놓겠습니다.Name as varchar,startdate as datetime그리고.repeats as int

Name    | StartDate            |   Repeats
-------------------------------------
Meeting | 2012-12-10 00:00:00  |   7
Lunch   | 2012-12-10 00:00:00  |   1

이제 집계표를 사용하여 다음을 사용하여 두 날짜 사이의 모든 날짜를 선택할 수 있습니다.

SELECT DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY) as showdate
FROM `tally`
WHERE (DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY)<='2012-12-20 00:00:00')
ORDER BY Id ASC


ShowDate
-------------------------------------
2012-12-09 00:00:00
2012-12-10 00:00:00
2012-12-11 00:00:00
2012-12-12 00:00:00
2012-12-13 00:00:00
2012-12-14 00:00:00
2012-12-15 00:00:00
2012-12-16 00:00:00
2012-12-17 00:00:00
2012-12-18 00:00:00
2012-12-19 00:00:00
2012-12-20 00:00:00

그런 다음 이벤트 테이블에 이를 결합하여 시작 날짜와 표시 날짜의 차이를 계산합니다..repeats 값이 과 같은 0.

모두 합하면 다음과 같습니다.

SELECT E.Id, E.Name, E.StartDate, E.Repeats, A.ShowDate, DATEDIFF(E.StartDate, A.ShowDate) AS diff
FROM events AS E, (
    SELECT DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY) as showdate
    FROM `tally`
    WHERE (DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY)<='2012-12-20 00:00:00')
    ORDER BY Id ASC
) a
WHERE MOD(DATEDIFF(E.StartDate, A.ShowDate), E.Repeats)=0
AND A.ShowDate>=E.StartDate

결과적으로

Id  | Name       |StartDate             | Repeats   | ShowDate              | diff
---------------------------------------------------------------------------------
1   | Meeting    | 2012-12-10 00:00:00  | 7         | 2012-12-10 00:00:00   | 0
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-10 00:00:00   | 0
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-11 00:00:00   | -1
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-12 00:00:00   | -2
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-13 00:00:00   | -3
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-14 00:00:00   | -4
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-15 00:00:00   | -5
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-16 00:00:00   | -6
1   | Meeting    | 2012-12-10 00:00:00  | 7         | 2012-12-17 00:00:00   | -7
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-17 00:00:00   | -7
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-18 00:00:00   | -8
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-19 00:00:00   | -9
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-20 00:00:00   | -10

이제 여러분은 일의 속도를 높일 수 있습니다.예를 들어, 날짜가 추가된 집계 테이블을 사용하지 않고 모든 날짜를 직접 선택할 수 있도록 테이블에 직접 날짜를 저장합니다.캐시할 수 있고 다시 계산할 필요가 없는 모든 것이 좋습니다.

언급URL : https://stackoverflow.com/questions/10972669/sql-infinite-calendar-pattern

반응형