ক্যালেন্ডার পুনরাবৃত্তি / পুনরাবৃত্তি ইভেন্ট - সেরা স্টোরেজ পদ্ধতি


311

আমি একটি কাস্টম ইভেন্ট সিস্টেম তৈরি করছি এবং আপনার যদি এমন কোনও পুনরাবৃত্তি ইভেন্ট থাকে যা দেখে মনে হচ্ছে:

ইভেন্ট এ 3 মার্চ, ২০১১ থেকে প্রতি 4 দিনে পুনরাবৃত্তি করে

অথবা

ইভেন্ট বি মঙ্গলবার 1 মার্চ, 2011 থেকে প্রতি 2 সপ্তাহে পুনরাবৃত্তি করে

আমি কীভাবে এটি একটি ডেটাবেজে সংরক্ষণ করতে পারি যাতে এটি দেখার পক্ষে সহজ হয়। বিপুল সংখ্যক ইভেন্ট থাকলে আমি পারফরম্যান্সের সমস্যাগুলি চাই না, এবং ক্যালেন্ডারটি রেন্ডার করার সময় আমাকে প্রত্যেকের মধ্য দিয়ে যেতে হবে।


1299132000 হার্ডকোড কেন আপনি ব্যাখ্যা করতে পারেন ? যদি আমার প্রদত্ত শেষের তারিখের জন্য উপস্থিতি তারিখ এবং ব্যবহারকারী পেতে প্রয়োজন হয় তবে এটি কী করবে?
মুরালি মুরুগেসন

@ মুরালি ছেলে এটি পুরানো, তবে আমি নিশ্চিত যে 1299132000 এর বর্তমান তারিখ হওয়ার কথা।
ব্র্যান্ডন ওয়াম্বল্ট

@ ব্র্যান্ডনওয়াম্বল্ট, আমি এসকিউএল সার্ভার দিয়ে আপনার ধারণার চেষ্টা করেছি। stackoverflow.com/questions/20286332/display-next-event-date । আমি সি # সংস্করণ
বিলা

উত্তর:


211

"সরল" পুনরাবৃত্তি প্যাটার্নগুলি সংরক্ষণ করা

আমার পিএইচপি / মাইএসকিউএল ভিত্তিক ক্যালেন্ডারের জন্য, আমি যতটা সম্ভব দক্ষতার সাথে পুনরাবৃত্তি / পুনরাবৃত্ত ইভেন্টের তথ্য সঞ্চয় করতে চেয়েছিলাম। আমি বড় সংখ্যক সারি রাখতে চাইনি, এবং আমি নির্দিষ্ট তারিখে ঘটে যাওয়া সমস্ত ইভেন্টগুলি খুব সহজেই অনুসন্ধান করতে চেয়েছিলাম।

নিয়মিত বিরতিতে যেমন প্রতি দিন, প্রতি এন দিন, প্রতি সপ্তাহে, প্রতি মাসে, ইত্যাদি ইত্যাদিতে ঘটে যাওয়া পুনরাবৃত্তি তথ্য সংরক্ষণ করার জন্য নীচের পদ্ধতিটি দুর্দান্ত This পৃথকভাবে প্রতি সপ্তাহে মঙ্গলবার এবং প্রতি সপ্তাহে বৃহস্পতিবার থেকে শুরু হবে।

ধরে নিচ্ছি আমার কাছে দুটি টেবিল রয়েছে, একটিতে এটি বলা হয় events:

ID    NAME
1     Sample Event
2     Another Event

এবং একটি টেবিল এর নামে পরিচিত events_meta:

ID    event_id      meta_key           meta_value
1     1             repeat_start       1299132000
2     1             repeat_interval_1  432000

পুনরায়_ স্টার্টটি একটি ইউনিক্স টাইমস্ট্যাম্প হিসাবে সময় না নিয়ে একটি তারিখ হওয়ার সাথে এবং অন্তরালগুলির মধ্যে কয়েক সেকেন্ডের মধ্যে পুনরাবৃত্তি করুন (432000 5 দিন)।

পুনরাবৃত্তি_আইন্টারওয়াল আইডি 1 এর পুনরাবৃত্তি_ স্টার্ট সহ যায় 1. সুতরাং আমার যদি প্রতিযোগিতায় প্রতি মঙ্গলবার এবং প্রতি বৃহস্পতিবার পুনরাবৃত্তি ঘটে এমন একটি ইভেন্ট থাকে তবে পুনরাবৃত্তি_ইন্টারওয়ালটি হবে 604800 (7 দিন), এবং 2 বার বার_আরচনা এবং 2 পুনর্বার_আপনার থাকবে। টেবিলটি দেখতে এমন হবে:

ID    event_id      meta_key           meta_value
1     1             repeat_start       1298959200 -- This is for the Tuesday repeat
2     1             repeat_interval_1  604800
3     1             repeat_start       1299132000 -- This is for the Thursday repeat
4     1             repeat_interval_3  604800
5     2             repeat_start       1299132000
6     2             repeat_interval_5  1          -- Using 1 as a value gives us an event that only happens once

তারপরে, যদি আপনার কাছে এমন কোনও ক্যালেন্ডার থাকে যা প্রতিটি দিন জুড়ে যায়, যে দিনটি ঘটেছিল তার জন্য ঘটনাগুলি ধরে রাখলে, ক্যোয়ারীটি দেখতে এমন হবে:

SELECT EV.*
FROM `events` EV
RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id`
RIGHT JOIN `events_meta` EM2 ON EM2.`meta_key` = CONCAT( 'repeat_interval_', EM1.`id` )
WHERE EM1.meta_key = 'repeat_start'
    AND (
        ( CASE ( 1299132000 - EM1.`meta_value` )
            WHEN 0
              THEN 1
            ELSE ( 1299132000 - EM1.`meta_value` )
          END
        ) / EM2.`meta_value`
    ) = 1
LIMIT 0 , 30

প্রতিস্থাপন করা হচ্ছে {current_timestamp}বর্তমান তারিখ জন্য UNIX টাইমস্ট্যাম্প সঙ্গে (বিয়োগ সময়, তাই ঘন্টা, মিনিট এবং দ্বিতীয় মান 0 সেট করা হবে)।

আশা করি এটি অন্য কাউকেও সহায়তা করবে!


"কমপ্লেক্স" পুনরাবৃত্তি প্যাটার্নগুলি সঞ্চয় করে

জটিল পদ্ধতিতে যেমন সংরক্ষণের জন্য এই পদ্ধতিটি আরও ভাল

Event A repeats every month on the 3rd of the month starting on March 3, 2011

অথবা

Event A repeats Friday of the 2nd week of the month starting on March 11, 2011

আমি সর্বাধিক নমনীয়তার জন্য এটি উপরের সিস্টেমের সাথে একত্রিত করার প্রস্তাব দিই। এর জন্য সারণীগুলি পছন্দ করতে হবে:

ID    NAME
1     Sample Event
2     Another Event

এবং একটি টেবিল এর নামে পরিচিত events_meta:

ID    event_id      meta_key           meta_value
1     1             repeat_start       1299132000 -- March 3rd, 2011
2     1             repeat_year_1      *
3     1             repeat_month_1     *
4     1             repeat_week_im_1   2
5     1             repeat_weekday_1   6

repeat_week_imবর্তমান মাসের সপ্তাহটি উপস্থাপন করে, যা সম্ভাব্য 1 এবং 5 এর মধ্যে হতে পারে। repeat_weekdayসপ্তাহের দিন, 1-7।

এখন ধরে নিই যে আপনি আপনার ক্যালেন্ডারে মাসের ভিউ তৈরি করতে দিন / সপ্তাহ কাটিয়ে চলেছেন, আপনি এই জাতীয় একটি প্রশ্ন তৈরি করতে পারেন:

SELECT EV . *
FROM `events` AS EV
JOIN `events_meta` EM1 ON EM1.event_id = EV.id
AND EM1.meta_key = 'repeat_start'
LEFT JOIN `events_meta` EM2 ON EM2.meta_key = CONCAT( 'repeat_year_', EM1.id )
LEFT JOIN `events_meta` EM3 ON EM3.meta_key = CONCAT( 'repeat_month_', EM1.id )
LEFT JOIN `events_meta` EM4 ON EM4.meta_key = CONCAT( 'repeat_week_im_', EM1.id )
LEFT JOIN `events_meta` EM5 ON EM5.meta_key = CONCAT( 'repeat_weekday_', EM1.id )
WHERE (
  EM2.meta_value =2011
  OR EM2.meta_value = '*'
)
AND (
  EM3.meta_value =4
  OR EM3.meta_value = '*'
)
AND (
  EM4.meta_value =2
  OR EM4.meta_value = '*'
)
AND (
  EM5.meta_value =6
  OR EM5.meta_value = '*'
)
AND EM1.meta_value >= {current_timestamp}
LIMIT 0 , 30

উপরোক্ত পদ্ধতির সাথে এটি একত্রে সর্বাধিক পুনরাবৃত্তি / পুনরাবৃত্ত ইভেন্ট নিদর্শনগুলি কভার করার জন্য মিলিত হতে পারে। আমি যদি কিছু মিস করি তবে একটি মন্তব্য করুন।


1
আমি আপনার স্টোরিং "সাধারণ" পুনরাবৃত্তি প্যাটার্ন চেষ্টা করছি। যদি আমাকে মঙ্গলবার প্রতি সপ্তাহে পুনরাবৃত্তি করার প্রয়োজন হয় তবে আমার পুনরাবৃত্তি_স্টার্টটি সংশোধন করতে হবে বা শেষ তারিখের সাথে একটি নতুন রেকর্ড তৈরি করতে হবে। বা প্রতি সপ্তাহে প্রথম পুনর্বার_আরম্ভের ভিত্তিতে এর পুনরাবৃত্তি করার কোন উপায় আছে ???
লু

1
: আপনার উত্তর একটি মহান সাহায্য @roguecoder ছিল কিন্তু এটা বেশ বাদুড় বন্ধ কাজ করে নি ... আমি এই পোস্টে পরে আমার উত্তর পাওয়া stackoverflow.com/questions/10545869/...
বেন সিনক্লেয়ার

1
ইন AND ( ( CASE ( 1299132000 - EM1.meta_value ) WHEN 0 THEN 1 ELSE ( 1299132000 - EM1.meta_value) END ) / EM2.meta_value ) = 1এই হয় / EM2.meta_valueভুলভাবে স্থাপন?
মুরালি মুরুগেসন

1
এটি একটি দুর্দান্ত সাহায্য। আপনি কীভাবে এগুলিকে স্বতন্ত্র রেকর্ড হিসাবে অ্যাক্সেসের পরামর্শ দিবেন, বলুন, যদি আপনি ব্যক্তিগত ইভেন্টগুলিতে মন্তব্য করতে বা চেক-ইন করতে চান?
জনশ্রী 5:44

26
এটি লক্ষণীয় যে আপনার পুনরাবৃত্ত বিরতিগুলির জন্য, যেমন 86400দিনে এক সেকেন্ডের জন্য হার্ডকোডযুক্ত মানগুলি ব্যবহার করা উচিত নয় , কারণ এটি দিবালোকের সঞ্চয়ী সময়ের জন্য সময় দেয় না। তা উড়ে উপর পরিবর্তনশীল এসব নিরূপণ এবং এর পরিবর্তে সঞ্চয় করতে আরো উপযুক্ত হচ্ছে interval = dailyএবং interval_count = 1বা interval = monthlyএবং interval_count = 1
কোরি বলিউ

185

যদিও বর্তমানে গৃহীত উত্তরগুলি আমার পক্ষে একটি বিশাল সহায়ক ছিল, আমি কিছু দরকারী পরিবর্তনগুলি ভাগ করতে চেয়েছিলাম যা অনুসন্ধানগুলি সহজতর করে এবং কর্মক্ষমতা বাড়ায়।


"সাধারণ" পুনরাবৃত্তি ইভেন্ট

নিয়মিত বিরতিতে পুনরাবৃত্তি হওয়া ইভেন্টগুলি পরিচালনা করতে যেমন:

Repeat every other day 

অথবা

Repeat every week on Tuesday 

আপনার দুটি টেবিল তৈরি করা উচিত, যার eventsমধ্যে একটি বলা হয় :

ID    NAME
1     Sample Event
2     Another Event

এবং একটি টেবিল এর নামে পরিচিত events_meta:

ID    event_id      repeat_start       repeat_interval
1     1             1369008000         604800            -- Repeats every Monday after May 20th 2013
1     1             1369008000         604800            -- Also repeats every Friday after May 20th 2013

সঙ্গে repeat_startকোন সময় (মে 20th 2013 1369008000 অনুরূপ), এবং সঙ্গে একটি UNIX টাইমস্ট্যাম্প তারিখ হচ্ছে repeat_intervalঅন্তর মধ্যে একটি পরিমাণ সেকেন্ডের মধ্যে (604800 7 দিন)।

ক্যালেন্ডারে প্রতিটি দিন লুপ করে আপনি এই সাধারণ ক্যোয়ারী ব্যবহার করে পুনরাবৃত্তি ইভেন্টগুলি পেতে পারেন:

SELECT EV.*
FROM `events` EV
RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id`
WHERE  (( 1299736800 - repeat_start) % repeat_interval = 0 )

আপনার ক্যালেন্ডারে প্রতিটি তারিখের জন্য কেবল ইউনিক্স-টাইমস্ট্যাম্পে (1299736800) বিকল্প করুন।

মডুলোর ব্যবহার (% চিহ্ন) নোট করুন। এই প্রতীকটি নিয়মিত বিভাগের মতো, তবে ভাগফলের পরিবর্তে '' বাকী '' প্রদান করে এবং বর্তমানের তারিখটি পুনরায়_স্টার্ট থেকে পুনরাবৃত্তিমূলকের একক একাধিক হলে 0 হয়।

পারফরম্যান্স তুলনা

এটি পূর্বে প্রস্তাবিত "মেটা_কিজ" ভিত্তিক উত্তরের চেয়ে উল্লেখযোগ্যভাবে দ্রুত, যা নীচে ছিল:

SELECT EV.*
FROM `events` EV
RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id`
RIGHT JOIN `events_meta` EM2 ON EM2.`meta_key` = CONCAT( 'repeat_interval_', EM1.`id` )
WHERE EM1.meta_key = 'repeat_start'
    AND (
        ( CASE ( 1299132000 - EM1.`meta_value` )
            WHEN 0
              THEN 1
            ELSE ( 1299132000 - EM1.`meta_value` )
          END
        ) / EM2.`meta_value`
    ) = 1

আপনি যদি এই ক্যোয়ারির ব্যাখ্যা দেন, আপনি নোট করবেন যে এটিতে একটি জয়েন বাফার ব্যবহারের প্রয়োজন ছিল:

+----+-------------+-------+--------+---------------+---------+---------+------------------+------+--------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref              | rows | Extra                          |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+--------------------------------+
|  1 | SIMPLE      | EM1   | ALL    | NULL          | NULL    | NULL    | NULL             |    2 | Using where                    |
|  1 | SIMPLE      | EV    | eq_ref | PRIMARY       | PRIMARY | 4       | bcs.EM1.event_id |    1 |                                |
|  1 | SIMPLE      | EM2   | ALL    | NULL          | NULL    | NULL    | NULL             |    2 | Using where; Using join buffer |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+--------------------------------+

উপরের 1 টি সংযুক্ত সমাধানের জন্য এ জাতীয় কোনও বাফার দরকার নেই।


"জটিল" প্যাটার্নস

এই জাতীয় পুনরাবৃত্ত নিয়মগুলিকে সমর্থন করার জন্য আপনি আরও জটিল ধরণের জন্য সমর্থন যুক্ত করতে পারেন:

Event A repeats every month on the 3rd of the month starting on March 3, 2011

অথবা

Event A repeats second Friday of the month starting on March 11, 2011

আপনার ইভেন্টের টেবিলটি হুবহু দেখতে পাওয়া যাবে:

ID    NAME
1     Sample Event
2     Another Event

তারপরে এই জটিল বিধিগুলির জন্য সমর্থন যুক্ত করতে কলামগুলিকে events_metaপছন্দ করতে যুক্ত করুন :

ID    event_id      repeat_start       repeat_interval    repeat_year    repeat_month    repeat_day    repeat_week    repeat_weekday
1     1             1369008000         604800             NULL           NULL            NULL          NULL           NULL             -- Repeats every Monday after May 20, 2013
1     1             1368144000         604800             NULL           NULL            NULL          NULL           NULL             -- Repeats every Friday after May 10, 2013
2     2             1369008000         NULL               2013           *               *             2              5                -- Repeats on Friday of the 2nd week in every month    

মনে রাখবেন আপনি কেবল হয় একটি নির্দিষ্ট করতে হবে repeat_interval বা একটি সেট repeat_year, repeat_month, repeat_day, repeat_week, এবং repeat_weekdayডেটা।

এটি একই সাথে উভয় প্রকারের নির্বাচনকে খুব সহজ করে তোলে। প্রতিটি দিন কেবল লুপ করুন এবং সঠিক মানগুলি পূরণ করুন (70 ই জুন 2013 এর জন্য 1370563200 এবং তারপরে বছর, মাস, দিন, সপ্তাহের সংখ্যা এবং সপ্তাহের দিন):

SELECT EV.*
FROM `events` EV
RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id`
WHERE  (( 1370563200 - repeat_start) % repeat_interval = 0 )
  OR ( 
    (repeat_year = 2013 OR repeat_year = '*' )
    AND
    (repeat_month = 6 OR repeat_month = '*' )
    AND
    (repeat_day = 7 OR repeat_day = '*' )
    AND
    (repeat_week = 2 OR repeat_week = '*' )
    AND
    (repeat_weekday = 5 OR repeat_weekday = '*' )
    AND repeat_start <= 1370563200
  )

এটি ২ য় সপ্তাহের শুক্রবারে পুনরাবৃত্তি হওয়া সমস্ত ইভেন্টের পাশাপাশি প্রতি শুক্রবার পুনরাবৃত্তি করে এমন কোনও ইভেন্ট ফেরত দেয়, সুতরাং এটি ইভেন্টের আইডি 1 এবং 2 উভয়ই প্রত্যাবর্তন করে:

ID    NAME
1     Sample Event
2     Another Event

* উপরের এসকিউএল-তে সিডিনোট আমি পিএইচপি তারিখের ডিফল্ট সপ্তাহের দিন সূচকগুলি ব্যবহার করেছি, তাই শুক্রবারের জন্য "5"


আশা করি এটি অন্যকে ততটাই সহায়তা করবে যতটা আসল উত্তরটি আমাকে সহায়তা করেছিল!


6
এটি আশ্চর্যজনক, আপনাকে ধন্যবাদ! আপনার কী ধারণা আছে যে আপনি "প্রথম সোমবার প্রতি 2 মাস" বা "প্রথম সোমবার প্রতি 3 মাস" ইত্যাদি এনকোড করবেন?
জর্দান লেভ

6
আমি সম্মত এই আশ্চর্যজনক। জর্ডান লেভের মতো একই দ্বিধায় পড়ে গেলাম। পুনরাবৃত্তি_ইন্টারওয়াল ক্ষেত্র পুনরাবৃত্তি করা মাসগুলির পক্ষে ভাল না কারণ কিছু মাস অন্যদের চেয়ে দীর্ঘ হয়। এছাড়াও, আপনি কীভাবে পুনরাবৃত্ত ইভেন্টের সময়কাল সীমাবদ্ধ করেন। অর্থাত্, প্রতি 2 মাসে প্রথম সোমবার 8 মাসের জন্য। টেবিলের কিছু শেষের তারিখ থাকা উচিত।
অবিনাদি

11
এটি একটি দুর্দান্ত উত্তর। আমি পুনরাবৃত্তি_ইন্টারওয়াল ছেড়ে গিয়েছি এবং পুনরাবৃত্তি_ তারিখটি জুড়েছি, তবে এই উত্তরটি যথেষ্ট সাহায্য করেছিল।
আয়েন কলিন্স

3
টিপ: জটিল নিদর্শনগুলির জন্য, কেউ repeat_intervalকলামটি মুছে ফেলতে এবং পরবর্তী কলামগুলিতে এটি উপস্থাপন করতে পারে (যেমন repeat_year, ইত্যাদি) প্রথম সারিতে, ২০ শে মে, ২০১৩ এর পরে প্রতি সোমবার পুনরাবৃত্তি করার পরিস্থিতিটি একটিতে 1 রেখে প্রতিনিধিত্ব করা যেতে পারে repeat_weekdayএবং *অন্যান্য কলামগুলিতে একটি।
মুসুবি

3
@ অলিভিমারম্যাট্রোট @ মিলস ধারণাটি হ'ল আপনি যে ক্ষেত্রটি স্পষ্টভাবে স্থির করতে চান সেটি নির্ধারণ করুন এবং বাকীটি ওয়াইল্ডকার্ডে রাখবেন *। সুতরাং "প্রতি মাসে 3 য় প্রতি" জন্য আপনি কেবল 3 তে সেট repeat_dayকরেছেন, বাকি repeatক্ষেত্রগুলি * ( repeat_intervalনাল ছেড়ে যান ) এবং আপনার অ্যাঙ্কারের তারিখ হিসাবে 3 মার্চ, 2011-র জন্য ইউনিক্স টাইমকোডে রিপাইট_স্টার্ট সেট করুন।
অহফনার 18'19

28

বর্ধন: তারিখের সাথে টাইমস্ট্যাম্প প্রতিস্থাপন করুন

গৃহীত উত্তরের একটি ছোট বৃদ্ধি হিসাবে যা পরবর্তীতে অহফনার দ্বারা পরিশ্রুত করা হয়েছিল - টাইমস্ট্যাম্পের পরিবর্তে তারিখের ফর্ম্যাট ব্যবহার করা সম্ভব। সুবিধাগুলি হ'ল:

  1. ডাটাবেসে পঠনযোগ্য তারিখ
  2. বছর> 2038 এবং টাইমস্ট্যাম্প নিয়ে কোনও সমস্যা নেই
  3. অপসারণের টাইমস্ট্যাম্পগুলি সম্পর্কে সতর্কতা অবলম্বন করা উচিত যা মৌসুমী সমন্বিত তারিখগুলির উপর ভিত্তি করে the ইউকেতে ২৮ শে জুন ২৮ শে ডিসেম্বর থেকে এক ঘন্টা আগে শুরু হয় তাই কোনও তারিখ থেকে টাইমস্ট্যাম্প নেওয়া পুনরাবৃত্তির অ্যালগরিদমকে ভেঙে ফেলতে পারে।

এটি করতে, ডিবি পরিবর্তন করে repeat_start'তারিখ' টাইপ হিসাবে সংরক্ষণ করা হবে এবং repeat_intervalএখন কয়েক সেকেন্ডের চেয়ে দিন ধরে রাখা উচিত। অর্থাত 7 দিনের পুনরাবৃত্তির জন্য 7।

স্কয়ার লাইনটি পরিবর্তন করুন:

WHERE (( 1370563200 - repeat_start) % repeat_interval = 0 )

প্রতি:

WHERE ( DATEDIFF( '2013-6-7', repeat_start ) % repeat_interval = 0)

অন্য সব কিছুই একই থাকে। Simples!


তাহলে আমি যদি চাই যে আমার ইভেন্টটি বছরের পর বছর পুনরাবৃত্তি করে? পুনরুদ্ধারকালে 365 দিন সঞ্চয় করা উচিত? যদি তাদের বছরের 366 দিন থাকে?
টিজেগার

3
@ জর্জ02 যদি ইভেন্টটি বার্ষিক হয় আপনি পুনরাবৃত্তি_আন্টারওয়াল ছেড়ে চলে যাবেন এবং পুনরাবৃত্তি_আর আপনার পুনরাবৃত্তির উপর নির্ভর করে আপনি 11 শে মার্চ বা রিপিট_মোথ, রিপিট_উইক এবং রিপিট_উইকডে এপ্রিলের ২ য় মঙ্গলবার সেট করতে পারেন।
jerrygarciuh

25

আমি এই গাইডটি অনুসরণ করব: https://github.com/bmoeskau/Extensible/blob/master/recurrence-overview.md

এছাড়াও নিশ্চিত হয়ে নিন যে আপনি আইসিএল ফর্ম্যাটটি ব্যবহার করেছেন যাতে চাকাটি পুনরায় সঞ্চার করতে না পারে এবং নিয়ম # 0 মনে রাখবেন না : পৃথক পুনরাবৃত্ত ইভেন্ট ইভেন্টগুলি আপনার ডাটাবেসে সারি হিসাবে সংরক্ষণ করবেন না!


2
আপনি কীভাবে কোনও সুনির্দিষ্ট ইভেন্টে অংশ নেওয়া ট্র্যাকিং ব্যবহারকারীদের মডেল করবেন? এই ক্ষেত্রে বিধি # 0 থেকে বিরতি দেওয়া কি বোধগম্য?
ড্যানি সুলিভান

2
@ ড্যানি সুলিভান আমার মাথার উপরের দিক থেকে আমার attendedEventসাথে আরও একটি সত্তা থাকবে baseInstanceIdএবং instanceStartDateএটি উদাহরণস্বরূপ যে বেস ইভেন্টটি থেকে আপনি পুনরাবৃত্ত নিয়মগুলি ক্যালেন্ডার ভিউ তৈরি করেছেন এবং সেই নির্দিষ্ট উদাহরণের তথ্য নির্দিষ্ট করার জন্য শুরুর তারিখটি ব্যবহার করুন তারপরে এই সত্তাটিও পারে এর মতো কিছু রয়েছে attendedListIdযা অন্য টেবিলে নিয়ে যায় id,attendedUserId
গাল ব্রাচা

@ ড্যানি সুলিভান আমি জানি আপনি যখন জিজ্ঞাসা করেছেন তখন কিছুক্ষণ হয়ে গেল। তবে পূর্ববর্তী মন্তব্যের বাইরে আপনি সর্বদা বিপরীত অনুসন্ধান করতে পারতেন কিনা তা দেখার জন্য যদি সেই ব্যবহারকারীর ইভেন্ট পুনরাবৃত্তির ধরণের অংশ ছিল কিনা। তারা আপনাকে বলবে যে তারা অন্তত ইভেন্টটির জন্য নির্ধারিত ছিল কিনা। তারা প্রকৃতপক্ষে অংশ নিয়েছিল বা না এগুলি একটি ভিন্ন গল্প যা ড্যানি সুলিভানের মন্তব্যের পাতায় আরও থাকবে।
ব্রোগার্স

24

আপনার আগ্রহী আপনার সকলের জন্য, আপনি এখন কয়েক মিনিটের মধ্যেই শুরু করতে কপি এবং পেস্ট করতে পারেন। আমি মতামত হিসাবে পরামর্শ হিসাবে গ্রহণ করতে পারে। যদি আমি কিছু মিস করছি তবে আমাকে জানান।

"সম্পূর্ণ সংস্করণ":

ঘটনাবলী

+ + ---------- + + ---------------- + +
| আইডি | নাম |
+ + ---------- + + ---------------- + +
| 1 | নমুনা ইভেন্ট 1 |
| 2 | দ্বিতীয় ঘটনা |
| 3 | তৃতীয় ঘটনা |
+ + ---------- + + ---------------- + +

events_meta

+ + ---- + + ---------- + + -------------- + + ------------------ + + ------------- + + -------------- + + ------------ + + ------- ------ + + ---------------- + +
| আইডি | ইভেন্ট_আইডি | পুনরাবৃত্তি_আরম্ভ | পুনরাবৃত্তিময় | রিপিট_ইয়ার | পুনরাবৃত্তি_মোথ | পুনরাবৃত্তি_দিন | পুনরাবৃত্তি_উইক | পুনরাবৃত্তি_উইকদিন |
+ + ---- + + ---------- + + -------------- + + ------------------ + + ------------- + + -------------- + + ------------ + + ------- ------ + + ---------------- + +
| 1 | 1 | 2014-07-04 | 7 | নুল | নুল | নুল | নুল | নুল |
| 2 | 2 | 2014-06-26 | নুল | 2014 | * | * | 2 | 5 |
| 3 | 3 | 2014-07-04 | নুল | * | * | * | * | 5 |
+ + ---- + + ---------- + + -------------- + + ------------------ + + ------------- + + -------------- + + ------------ + + ------- ------ + + ---------------- + +

এসকিউএল কোড:

CREATE TABLE IF NOT EXISTS `events` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `NAME` varchar(255) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;

--
-- Dumping data for table `events`
--

INSERT INTO `events` (`ID`, `NAME`) VALUES
(1, 'Sample event'),
(2, 'Another event'),
(3, 'Third event...');

CREATE TABLE IF NOT EXISTS `events_meta` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `event_id` int(11) NOT NULL,
  `repeat_start` date NOT NULL,
  `repeat_interval` varchar(255) NOT NULL,
  `repeat_year` varchar(255) NOT NULL,
  `repeat_month` varchar(255) NOT NULL,
  `repeat_day` varchar(255) NOT NULL,
  `repeat_week` varchar(255) NOT NULL,
  `repeat_weekday` varchar(255) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `ID` (`ID`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;

--
-- Dumping data for table `events_meta`
--

INSERT INTO `events_meta` (`ID`, `event_id`, `repeat_start`, `repeat_interval`, `repeat_year`, `repeat_month`, `repeat_day`, `repeat_week`, `repeat_weekday`) VALUES
(1, 1, '2014-07-04', '7', 'NULL', 'NULL', 'NULL', 'NULL', 'NULL'),
(2, 2, '2014-06-26', 'NULL', '2014', '*', '*', '2', '5'),
(3, 3, '2014-07-04', 'NULL', '*', '*', '*', '*', '1');

মাইএসকিউএল এক্সপোর্ট হিসাবে উপলব্ধ (সহজ অ্যাক্সেসের জন্য)

পিএইচপি উদাহরণ কোড সূচক। Php:

<?php
    require 'connect.php';    

    $now = strtotime("yesterday");

    $pushToFirst = -11;
    for($i = $pushToFirst; $i < $pushToFirst+30; $i++)
    {
        $now = strtotime("+".$i." day");
        $year = date("Y", $now);
        $month = date("m", $now);
        $day = date("d", $now);
        $nowString = $year . "-" . $month . "-" . $day;
        $week = (int) ((date('d', $now) - 1) / 7) + 1;
        $weekday = date("N", $now);

        echo $nowString . "<br />";
        echo $week . " " . $weekday . "<br />";



        $sql = "SELECT EV.*
                FROM `events` EV
                RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id`
                WHERE ( DATEDIFF( '$nowString', repeat_start ) % repeat_interval = 0 )
                OR ( 
                    (repeat_year = $year OR repeat_year = '*' )
                    AND
                    (repeat_month = $month OR repeat_month = '*' )
                    AND
                    (repeat_day = $day OR repeat_day = '*' )
                    AND
                    (repeat_week = $week OR repeat_week = '*' )
                    AND
                    (repeat_weekday = $weekday OR repeat_weekday = '*' )
                    AND repeat_start <= DATE('$nowString')
                )";
        foreach ($dbConnect->query($sql) as $row) {
            print $row['ID'] . "\t";
            print $row['NAME'] . "<br />";
        }

        echo "<br /><br /><br />";
    }
?>

পিএইচপি উদাহরণ কোড সংযোগ.এফপি:

<?
// ----------------------------------------------------------------------------------------------------
//                                       Connecting to database
// ----------------------------------------------------------------------------------------------------
// Database variables
$username = "";
$password = "";
$hostname = ""; 
$database = ""; 

// Try to connect to database and set charset to UTF8
try {
    $dbConnect = new PDO("mysql:host=$hostname;dbname=$database;charset=utf8", $username, $password);
    $dbConnect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

} catch(PDOException $e) {
    echo 'ERROR: ' . $e->getMessage();
}
// ----------------------------------------------------------------------------------------------------
//                                      / Connecting to database
// ----------------------------------------------------------------------------------------------------
?>

এছাড়াও পিএইচপি কোডটি এখানে (আরও ভাল পঠনযোগ্যতার জন্য) উপলভ্য:
সূচক.পিএফপি
এবং
সংযোগ.এফপি
এখন সেট আপ করতে আপনাকে কয়েক মিনিট সময় নিতে হবে। ঘন্টা নয়। :)


2
কীভাবে আমি তারিখের মধ্যে থাকা সমস্ত পুনরাবৃত্ত ইভেন্টগুলি পেতে জিজ্ঞাসা করতে পারি .. এটিই 2014-10-01 থেকে 2014-12-30 এর মধ্যে সমস্ত পুনরাবৃত্ত ইভেন্টগুলি পেতে। আপনার পোস্টের জন্য ধন্যবাদ
ওয়েল উইশার

@Wellwisher - পুনরাবৃত্তি ... যতক্ষণ না ও অস্থায়ী টেবিল stackoverflow.com/questions/34407833/...
ব্র্যাড কেন্ট

1
@ অ্যালেক্স পুনরাবৃত্ত ইভেন্ট থেকে কীভাবে আমি একটি দৃষ্টান্তটি মুছতে পারি।
পুগাঝেথি

1
আমি জানি যে এটি একটি পুরানো থ্রেড তবে পুনরাবৃত্তি_ * কলামগুলিতে কেন বারচার টাইপ? আপনি কি '*' এর পরিবর্তে একটি পূর্ণসংখ্যা এবং একটি নেতিবাচক মান ব্যবহার করতে পারেন?
অলিভিয়ার ম্যাট্রোট

1
কোডের জন্য ধন্যবাদ। তবে আমি অবশ্যই মন্তব্য করব যে আপনার ডিবি / ক্যোয়ারী বাস্তবায়ন কিছুটা বিঘ্নিত, এবং খুব অদক্ষ। উদাহরণস্বরূপ কেন এই জাতীয় সাধারণ কলামগুলির জন্য বারচর (255) ব্যবহার করুন (@ অলিভিমারম্যাট্রোট উল্লিখিত হিসাবে, আপনি পূর্ণসংখ্যা ব্যবহার করতে পারেন, এবং তা না হলেও কেন 255?)। এবং যদি আপনি কোয়েরিটি 30 বার পুনরাবৃত্তি করছেন তবে বিবৃতি বা পদ্ধতি ব্যবহার করবেন না কেন? কেউ যদি এটি বাস্তবায়ন করতে চলেছে তবে কেবলমাত্র প্রয়োজনে বলছি।
রনি

15

প্রস্তাবিত সমাধানগুলি কাজ করার সময়, আমি পূর্ণ ক্যালেন্ডার দিয়ে প্রয়োগ করার চেষ্টা করছিলাম এবং প্রতিটি ভিউয়ের জন্য এটির জন্য 90 টির বেশি ডাটাবেস কলগুলির প্রয়োজন হবে (এটি বর্তমান, পূর্ববর্তী এবং পরবর্তী মাসে লোড হয়), যা সম্পর্কে আমি খুব শিহরিত হইনি।

আমি একটি পুনরাবৃত্তি লাইব্রেরি https://github.com/tplaner/ পেয়েছি যেখানে আপনি কেবল প্রাসঙ্গিক নিয়মগুলি টানতে ডাটাবেসে নিয়ম এবং একটি ক্যোয়ারী সন্ধান করেন।

আশা করি এটি অন্য কাউকে সহায়তা করবে, কারণ আমি ভাল সমাধানের সন্ধান করার জন্য অনেক ঘন্টা ব্যয় করেছি।

সম্পাদনা করুন: এই লাইব্রেরিটি পিএইচপি-র জন্য


আমি ফুলক্যালেন্ডারও ব্যবহার করতে চাই। কিভাবে লাইব্রেরি আমাকে সাহায্য করতে পারে? প্রোপোয়ার ইভেন্টগুলি কীভাবে এক্সট্রাক্ট করবেন?
পাইর্নিক

@ পিয়ার্নিক - আমি ডকুমেন্টেশনের মতো লাইব্রেরিটি সেটআপ করব এবং যদি আপনি নির্দিষ্ট সমস্যাগুলির মধ্যে চলে যাচ্ছেন তবে আপনার সেটআপ করা কোড এবং আপনার যে সমস্যাগুলি রয়েছে সেগুলি সহ স্ট্যাকওভারফ্লো সম্পর্কে একটি নতুন প্রশ্ন খুলুন। আমি নিশ্চিত আপনি যদি কিছু সদস্যের মধ্যে এত প্রচেষ্টা করেন তবে আপনাকে সাহায্য করবে you
টিম রামসে

আমার অর্থ এই যে আপনাকে ব্যবহার করে Whenসমস্ত পুনরুদ্ধার তারিখগুলি ডাটাবেসে সংরক্ষণ করতে হবে বা সমস্ত পুনরুদ্ধার ইভেন্টগুলি পেতে হবে এবং ডাটাবেসে পিএইচপি নম্বরে তারিখ উত্পন্ন করতে হবে। আমি কি সঠিক?
পাইরেণিক

@ পিয়ার্নিক আপনি প্রাথমিক তারিখ এবং নিয়ম / গুলি ডাটাবেসে সংরক্ষণ করবেন এবং Whenসমস্ত তারিখ উত্পন্ন করতে ব্যবহার করবেন - যা প্রাথমিক সঞ্চিত তারিখ / বিধি থেকে উত্পন্ন হয়।
টিম রামসে

এটিও ভাল নয় - আপনি কোনও মাইএসকিএল কমান্ডেই সঠিক ইভেন্টগুলি পেতে পারবেন না - আপনাকে তার জন্য পিএইচপি ব্যবহার করতে হবে। যাইহোক ধন্যবাদ
পিয়ের্নিক

14

অ্যাপাচি ক্রোন জবসের মতো একটি প্রক্রিয়া কেন ব্যবহার করবেন না? http://en.wikipedia.org/wiki/Cron

ক্যালেন্ডার \ সময়সূচির জন্য আমি "বিটস" এর জন্য স্ট্যান্ডার্ড ক্যালেন্ডার পুনঃব্যবস্থা ইভেন্টগুলি সামঞ্জস্য করতে কিছুটা আলাদা মান ব্যবহার করতাম - পরিবর্তে [সপ্তাহের দিন (0 - 7), মাস (1 - 12), মাসের দিন (1 - 31), ঘন্টা (0 - 23), মিনিট (0 - 59)]

- আমি [বছর (প্রতি এন বছর পুনরাবৃত্তি), মাস (1 - 12), মাসের দিন (1 - 31), মাসের সপ্তাহ (1-5), সপ্তাহের দিন (0 - 7) এর মতো কিছু ব্যবহার করতাম ]

আশাকরি এটা সাহায্য করবে.


6
আমি মনে করি এটি সপ্তাহের অনেক বিকল্পের বিকল্প। হয় 1-7 বা 0-6 আরও সঠিক বলে মনে হচ্ছে।
অবিনাদি

2
পুনরাবৃত্তি সঞ্চয় করতে ক্রোন ব্যবহার করা ভাল। তবে বিষয়টি হ'ল এটি অনুসন্ধান করা খুব কঠিন।
স্টনি

@ ভ্লাদিমির আপনি কীভাবে সঞ্চয় করবেন, প্রতি দুই মঙ্গলবার (মঙ্গলবার প্রতি দুই সপ্তাহে)
জুলাইরাসং

@ জুলারাসং এই ওয়েবসাইটটির দেখে মনে হচ্ছে এর উত্তর রয়েছে: কোডারওয়াল.com
a- ক্রোন-

ক্রোনটির সীমিত অভিব্যক্তি রয়েছে, যেহেতু এটি রাষ্ট্রহীন (কেবলমাত্র বর্তমান / হাইপোথেরিকাল তারিখ / সময়কে একটি প্যাটার্নের সাথে তুলনা করে), এটি নির্দিষ্ট সাধারণ ব্যবসা / মানব নিদর্শনগুলিকে যেমন "প্রতি তৃতীয় দিন" বা "প্রতি hours ঘন্টা" উপস্থাপন করতে পারে না, যা শেষ ঘটনা মনে রাখা প্রয়োজন। এটি সুস্পষ্ট নয়; আপনি মনে করতে পারেন যে আপনি ক্রোনটবে কেবল দিন / 3 বা ঘন্টা / 7 বলছেন, তবে তারপরে মাস / দিন শেষে আপনার "বাকী" দিন / ঘন্টা থাকে যা 3 বা 7 এর চেয়ে কম হয়; সম্ভাব্য বিপর্যয়মূলক ফলাফল সহ।
জাইম গেরেরো

5

আমি এই ক্ষেত্রে কেবল একটি গুরূত্বপূর্ণ প্রোগ্রামিং ভাষা তৈরি করেছি। এটি সম্পর্কে সর্বোত্তম অংশটি হ'ল এটি স্কিমা কম এবং প্ল্যাটফর্ম স্বতন্ত্র। আপনাকে কেবল একটি সিলেক্টর প্রোগ্রাম লিখতে হবে, আপনার সময়সূচির জন্য, সিনট্যাক্স যা এখানে বর্ণিত বিধিগুলির সেট দ্বারা সীমাবদ্ধ রয়েছে -

https://github.com/tusharmath/sheql/wiki/Rules

নিয়মগুলি প্রসারণযোগ্য এবং আপনি স্কিমা মাইগ্রেশন ইত্যাদির চিন্তা না করে আপনি যে ধরণের পুনরাবৃত্তি যুক্তি সম্পাদন করতে চান তার উপর ভিত্তি করে যে কোনও ধরণের কাস্টমাইজেশন যুক্ত করতে পারেন etc.

এটি সম্পূর্ণ ভিন্ন পদ্ধতির এবং এর নিজস্ব কিছু অসুবিধাও থাকতে পারে।


4

সিস্টেম টেবিলগুলিতে সঞ্চিত মাইএসকিউএল ইভেন্টগুলির মতো খুব মনে হচ্ছে। আপনি কাঠামোটি দেখে বুঝতে পারেন যে কোন কলামগুলির প্রয়োজন নেই:

   EVENT_CATALOG: NULL
    EVENT_SCHEMA: myschema
      EVENT_NAME: e_store_ts
         DEFINER: jon@ghidora
      EVENT_BODY: SQL
EVENT_DEFINITION: INSERT INTO myschema.mytable VALUES (UNIX_TIMESTAMP())
      EVENT_TYPE: RECURRING
      EXECUTE_AT: NULL
  INTERVAL_VALUE: 5
  INTERVAL_FIELD: SECOND
        SQL_MODE: NULL
          STARTS: 0000-00-00 00:00:00
            ENDS: 0000-00-00 00:00:00
          STATUS: ENABLED
   ON_COMPLETION: NOT PRESERVE
         CREATED: 2006-02-09 22:36:06
    LAST_ALTERED: 2006-02-09 22:36:06
   LAST_EXECUTED: NULL
   EVENT_COMMENT:

4

আরআরইউএল স্ট্যান্ডার্ডটি ঠিক এই প্রয়োজনের জন্য তৈরি করা হয়েছে যেমন পুনরাবৃত্তিগুলি সংরক্ষণ এবং বোঝার জন্য। মাইক্রোসফ্ট এবং গুগল উভয়ই তাদের ক্যালেন্ডারের ইভেন্টগুলিতে এটি ব্যবহার করে। আরও বিশদ জন্য দয়া করে এই দস্তাবেজ মাধ্যমে যান। https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-rule.html


3

@ রাগ কোডার

এটা অসাধারণ!

আপনার কোডটি শেষে শেষে সহজ করার জন্য আপনি কেবল মডুলো অপারেশন (MOD বা% mysql তে%) ব্যবহার করতে পারেন:

পরিবর্তে:

AND (
    ( CASE ( 1299132000 - EM1.`meta_value` )
        WHEN 0
          THEN 1
        ELSE ( 1299132000 - EM1.`meta_value` )
      END
    ) / EM2.`meta_value`
) = 1

না:

$current_timestamp = 1299132000 ;

AND ( ('$current_timestamp' - EM1.`meta_value` ) MOD EM2.`meta_value`) = 1")

এটি আরও গ্রহণের জন্য, এমন কোনও ইভেন্ট অন্তর্ভুক্ত থাকতে পারে যা চিরতরে পুনরাবৃত্তি হয় না।

শেষ "পুনরাবৃত্তি_ইন্টারওয়াল_1" এর তারিখ বোঝাতে "পুনরাবৃত্তি_ইন্টারওয়াল_ভিত্তিক" এর মতো কিছু যুক্ত করা যেতে পারে। এটি যাইহোক, ক্যোয়ারীটিকে আরও জটিল করে তোলে এবং কীভাবে এটি করা যায় তা আমি সত্যিই বুঝতে পারি না ...

কেউ সাহায্য করতে পারে!


1

আপনার দেওয়া দুটি উদাহরণ খুব সহজ; এগুলিকে একটি সাধারণ ব্যবধান হিসাবে চিহ্নিত করা যেতে পারে (প্রথমটি চার দিন, দ্বিতীয়টি হচ্ছে 14 দিন)। আপনি এটি কীভাবে মডেল করবেন তা সম্পূর্ণরূপে আপনার পুনরাবৃত্তির জটিলতার উপর নির্ভর করবে। আপনার উপরের যা আছে তা যদি সত্যিই সহজ হয় তবে পুনরাবৃত্তির বিরতিতে একটি শুরুর তারিখ এবং দিনের সংখ্যা সংরক্ষণ করুন।

তবে, আপনার যদি পছন্দ মতো জিনিস সমর্থন করা প্রয়োজন

ইভেন্ট এ 3 মার্চ, 2011 থেকে শুরু হওয়া মাসের 3 য় প্রতি মাসে পুনরাবৃত্তি করে

অথবা

ইভেন্ট এ 11 মার্চ, 2011 থেকে শুরু হওয়া মাসের দ্বিতীয় শুক্রবার পুনরাবৃত্তি করে

তারপরে এটি আরও জটিল প্যাটার্ন।


1
আমি আরও জটিল নিয়মগুলি যুক্ত করেছিলাম যা আপনি ঠিক পরের মুহূর্তে বলেছেন তবে আপাতত নয়। আমি কীভাবে এসকিউএল কোয়েরিটি 7th ই মার্চ, ২০১১ এ ইভেন্টগুলি পেতে মডেল করব যাতে এটি আমার পুনরাবৃত্ত ইভেন্টটি পেতে পারে?
ব্র্যান্ডন ওয়াম্বল্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.