2012-02-14 18 views
6

मुझे पता है कि पुनरावर्ती घटनाओं के बारे में प्रश्न आम हैं, लेकिन मैं कैलेंडर ऐप्स के साथ अन्य आवर्ती कार्यक्रमों के बारे में इस विशिष्ट प्रश्न के उत्तर के साथ एक को खोजने में सक्षम नहीं हूं। मुख्य अंतर यह है कि हमारे ऐप में घटनाएं। केवल कैलेंडर प्रारूप के बजाय रिपोर्ट में या स्वयं ही देखा जाएगा, हालांकि कई तरीकों से वे बहुत समान हैं, शायद कैलेंडर के साथ जुड़े सामान से कम।पुनरावर्ती घटनाक्रम, एसक्यूएल क्वेरी

एक कैलेंडर अनुप्रयोग के लिए इसी प्रकार

। घटनाएं या तो एक-ऑफ आधार पर हो सकती हैं या आवर्ती हो सकती हैं। प्रत्येक गुरुवार या हर महीने के पहले सोमवार, भविष्य में कुछ पूर्व निर्धारित समय तक।

किसी घटना के समय आरंभ और समाप्ति तिथि और 'पुनरावृतिक प्रकार आईडी' शामिल एक घटना तालिका में जमा हो जाती है। यदि 'आवर्ती प्रकार' 'कोई नहीं' है तो प्रारंभ और समाप्ति तिथियां समान होंगी। इवेंट टेबल में एक आईडी को एक अलग तालिका में रखा जाता है जिसमें ईवेंट प्रकार का नाम होता है, उदा। बैठक 'या' साप्ताहिक रिपोर्ट '

एक और तालिका जो' पुनरावृतिक प्रकार 'जैसे की सूची होती है नहीं है 'कोई पुनरावृत्ति', 'हर सोमवार', 'महीने का पहला सोमवार' और 'महीने का अंतिम शनिवार'।

लुकअप आसान एक और तालिका प्रत्येक तिथि के बारे में प्रासंगिक जानकारी है, चाहे वह एक सोमवार की तरह साथ-साथ 1960 से 2060 के लिए तारीखों की एक सूची है, और सोमवार की जो घटना यह महीने में है करने के लिए।

यह अनुमति देता है एक देखने की तरह:

 
SELECT DISTINCT(e.eventid),n.nameid,n.firstname,n.lastname,d.dt,r.recurring 
FROM dates d 
LEFT JOIN recurringtypes r 
/* if event recurring every week E.g. 'Every Monday' */ 
ON (r.rectypeid BETWEEN 2 AND 8 AND r.day = d.dow) 
/* if event recurring every month E.g. 'First Monday, every month' */ 
OR ((r.rectypeid BETWEEN 9 AND 36) AND r.day = d.dow AND r.occurrence = d.occurrence) 
/* if event recurring every last week of month E.g. 'Last Monday, every month' */ 
OR (r.rectypeid >= 37 AND r.day = d.dow and r.islast = d.islast) 
LEFT JOIN events e on e.rectypeid = r.rectypeid 
LEFT JOIN eventtypes t ON e.eventtypeid = t.eventtypeid 
LEFT JOIN names n ON e.namesid = n.namesid 
WHERE (d.dt BETWEEN '2012/02/01' AND '2012/05/01') 
ORDER BY d.dt; 

कौन सा है कि वास्तव में क्या पुनरावर्ती ईवेंट को खोजने के लिए आवश्यक है, जैसे उत्पादन दे रही है:

 
+-----------+---------------+-------------------+-----------+------------+-------------------------------+ 
| eventid | nameid  | lastname   | firstname | dt   | recurring      | 
+-----------+---------------+-------------------+-----------+------------+-------------------------------+ 
| 3291788 |  1728449 | smith    | zoe  | 2012-02-02 | First Thursday, every month | 
| 3291797 |  1765432 |     |   | 2012-02-05 | First Sunday, every month  | 
| 3291798 |  1730147 |     |   | 2012-02-05 | First Sunday, every month  | 
| 3291803 |  1790061 | Carpenter   | Richie | 2012-02-06 | Every Monday     | 
| 3291805 |  1790061 | Carpenter   | Richie | 2012-02-08 | Second Wednesday, every month | 
| 3291803 |  1790061 | Carpenter   | Richie | 2012-02-13 | Every Monday     | 
| 3291799 |  1790061 | Carpenter   | Richie | 2012-02-15 | Third Wednesday, every month | 
| 3291803 |  1790061 | Carpenter   | Richie | 2012-02-20 | Every Monday     | 

करने के लिए कोई भी आवर्ती घटनाओं एक सरल प्रश्न इस्तेमाल किया जा सकता:

 
SELECT n.nameid,n.lastname,n.firstname,e.firstdate,e.eventid,'No' as Recurring 
FROM events e 
LEFT JOIN names n ON n.names = e.namesid 
AND e.rectypeid <= 1 
AND e.firstdate BETWEEN '2012/02/01' AND '2012/05/01' 
AND e.eventid IS NOT NULL ORDER BY e.firstdate; 
यह आउटपुट को पहली क्वेरी के समान ही देता है, लेकिन महत्वपूर्ण बात यह है कि तारीखें तालिका तालिका के बजाय ईवेंट टेबल से हैं।

मेरा प्रश्न है: मैं इन प्रश्नों कैसे जोड़ सकते हैं एक सूची है कि सभी घटनाओं, दोनों आवर्ती और गैर आवर्ती तारीख क्रम में होता है के साथ आने के लिए?


इन तालिकाओं और उनसे छोटा चयन, कुछ स्तंभ हैं और सभी अनुक्रमित संक्षिप्तता के लिए हटा दिया गया है :)। 'नाम' तालिका को उसी कारण से शामिल नहीं किया गया है।

 
CREATE TABLE events (
eventid int(11) NOT NULL AUTO_INCREMENT, 
eventtypeid int(11) DEFAULT '0', 
firstdate date DEFAULT '1960-01-01' COMMENT 'First event', 
lastdate date DEFAULT '1960-01-01' COMMENT 'Last event', 
rectypeid int(11) DEFAULT '1' 
); 
+---------+-------------+------------+------------+-----------+ 
| eventid | eventtypeid | firstdate | lastdate | rectypeid | 
+---------+-------------+------------+------------+-----------+ 
| 3291803 |   16 | 2012-02-03 | 2012-04-11 |   3 | 
| 3291797 |   8 | 2012-02-12 | 2012-02-22 |   9 | 
| 3291798 |   5 | 2012-02-12 | 2012-02-12 |   9 | 
| 3291788 |   8 | 2012-05-24 | 2015-01-16 |  13 | 
| 3291805 |   10 | 2012-01-04 | 2012-02-14 |  19 | 
| 3291799 |   16 | 2012-02-07 | 2012-10-24 |  26 | 
| 3291804 |   5 | 2012-02-03 | 2012-08-22 |  41 | 
+---------+-------------+------------+------------+-----------+ 
CREATE TABLE cmseventtypes (
eventtypeid int(11) NOT NULL AUTO_INCREMENT, 
eventtype varchar(50) DEFAULT '' COMMENT 'Event type AKA name' 
); 
+-------------+----------------------+ 
| eventtypeid | eventype    | 
+-------------+----------------------+ 
|   1 | Follow up meeting | 
|   2 | Reminder email due | 
|   3 | Monthly meeting  | 
|   4 | Weekly report  | 
|   5 | Golf practice  | 
+------------------------------------+ 
CREATE TABLE recurringtypes (
rectypeid int(11) NOT NULL AUTO_INCREMENT, 
recurring varchar(40) DEFAULT '', 
day tinyint(4) DEFAULT '0', 
occurrence tinyint(4) DEFAULT '0', 
islast tinyint(4) DEFAULT '0' 
); 
+-----------+---------------------------+------+------------+--------+ 
| rectypeid | recurring     | day | occurrence | islast | 
+-----------+---------------------------+------+------------+--------+ 
|   1 | No      | 0 |   0 |  0 | 
|   2 | Every Sunday    | 1 |   0 |  0 | 
|   3 | Every Monday    | 2 |   0 |  0 | 
|   4 | Every Tuesday    | 3 |   0 |  0 | 
|   5 | Every Wednesday   | 4 |   0 |  0 | 
|   6 | Every Thursday   | 5 |   0 |  0 | 
|   7 | Every Friday    | 6 |   0 |  0 | 
|   8 | Every Saturday   | 7 |   0 |  0 | 
|   9 | First Sunday, every month | 1 |   1 |  0 | 
|  10 | First Monday, every month | 2 |   1 |  0 | 
+-----------+---------------------------+------+------------+--------+ 
CREATE TABLE dates (
dt date NOT NULL COMMENT 'Date', 
daycount mediumint(9) NOT NULL DEFAULT '1', 
year smallint(6) NOT NULL DEFAULT '1970', 
month tinyint(4) NOT NULL DEFAULT '1', 
dom tinyint(4) NOT NULL DEFAULT '1', 
dow tinyint(4) NOT NULL DEFAULT '1', 
occurrence tinyint(4) NOT NULL DEFAULT '0', 
islast tinyint(1) NOT NULL DEFAULT '0' 
); 
+------------+----------+------+-------+-----+-----+------------+--------+ 
| dt   | daycount | year | month | dom | dow | occurrence | islast | 
+------------+----------+------+-------+-----+-----+------------+--------+ 
| 2012-02-02 | 734900 | 2012 |  2 | 2 | 5 |   1 |  0 | 
| 2012-02-03 | 734901 | 2012 |  2 | 3 | 6 |   1 |  0 | 
| 2012-02-04 | 734902 | 2012 |  2 | 4 | 7 |   1 |  0 | 
| 2012-02-05 | 734903 | 2012 |  2 | 5 | 1 |   1 |  0 | 
| 2012-02-06 | 734904 | 2012 |  2 | 6 | 2 |   1 |  0 | 
| 2012-02-07 | 734905 | 2012 |  2 | 7 | 3 |   1 |  0 | 
| 2012-02-08 | 734906 | 2012 |  2 | 8 | 4 |   2 |  0 | 
| 2012-02-09 | 734907 | 2012 |  2 | 9 | 5 |   2 |  0 | 
+------------+----------+------+-------+-----+-----+------------+--------+ 


हम पूरी तरह से ऊपर कोड या तालिका लेआउट का उपयोग करने पर सेट नहीं हैं, किसी भी काम कर समाधान स्वागत किया जाएगा।

How would you store possibly recurring times?

What's the best way to model recurring events in a calendar application?

Should I store dates or recurrence rules in my database when building a calendar app?

या

http://tools.ietf.org/html/rfc5545

मैं उन्हें बाहर की जाँच की है और वे बहुत ही उपयोगी है, लेकिन नहीं कर रहे थे: कृपया मुझे की ओर इंगित नहीं है जैसा कि हम इरादा करते हैं।

TIA

+0

'islast' क्या करता है? या 'दिनांक' तालिका में 'अवसर'? – Naltharial

+0

यदि 'इस्लास्ट' सेट एक महीने में एक दिन की आखिरी घटना (उदाहरण के लिए महीने में अंतिम सोमवार) होता है, तो घटना एक महीने में एक दिन की घटनाओं की गणना होती है (जैसे 'महीने में पहला सोमवार', 'दूसरा सोमवार महीने ') – blankabout

उत्तर

2

जब तक मैं कुछ याद कर रहा हूँ जवाब आश्चर्यजनक सरल है। मुझे एहसास नहीं हुआ था कि यूनियनों को उपनामों का उपयोग करके सामान्य कॉलम पर सॉर्ट किया जा सकता है, भले ही वे कॉलम अलग-अलग तालिकाओं से हों। तो पूरी क्वेरी होगा:

 
SELECT DISTINCT(e.eventid),n.nameid,n.firstname,n.lastname,d.dt AS dait,r.recurring 
FROM dates d 
LEFT JOIN recurringtypes r 
/* if event recurring every week E.g. 'Every Monday' */ 
ON (r.rectypeid BETWEEN 2 AND 8 AND r.day = d.dow) 
/* if event recurring every month E.g. 'First Monday, every month' */ 
OR ((r.rectypeid BETWEEN 9 AND 36) AND r.day = d.dow AND r.occurrence = d.occurrence) 
/* if event recurring every last week of month E.g. 'Last Monday, every month' */ 
OR (r.rectypeid >= 37 AND r.day = d.dow and r.islast = d.islast) 
LEFT JOIN events e on e.rectypeid = r.rectypeid 
LEFT JOIN eventtypes t ON e.eventtypeid = t.eventtypeid 
LEFT JOIN names n ON e.namesid = n.namesid 
WHERE (d.dt BETWEEN '2012/02/01' AND '2012/05/01') 
UNION 
SELECT e.eventid,n.nameid,n.lastname,n.firstname,e.firstdate AS dait,'No' as Recurring 
FROM events e 
LEFT JOIN names n ON n.names = e.namesid 
AND e.rectypeid <= 1 
WHERE e.firstdate BETWEEN '2012/02/01' AND '2012/05/01' 
ORDER BY dait; 

यह बताया गया है कि दिनांक को देख के लिए एक तालिका का उपयोग कर एक जोखिम है क्योंकि दिनांकों अंततः बाहर चला जाएगा, जो सच है, लेकिन गणना के लिए कि क्या एक तिथि उदाहरण के लिए, है, एक महीने में पहला सोमवार (या दूसरा, या चौथा या शायद चौथा और आखिरी), इस समय में शामिल होने के बजाय एसक्यूएल कोड की एक जटिल बिट की तरह लगता है।

2
SELECT DISTINCT(e.eventid),n.nameid,n.firstname,n.lastname,d.dt,r.recurring 
FROM dates d 
LEFT JOIN recurringtypes r 
/* if event recurring every week E.g. 'Every Monday' */ 
ON (r.rectypeid BETWEEN 2 AND 8 AND r.day = d.dow) 
/* if event recurring every month E.g. 'First Monday, every month' */ 
OR ((r.rectypeid BETWEEN 9 AND 36) AND r.day = d.dow AND r.occurrence = d.occurrence) 
/* if event recurring every last week of month E.g. 'Last Monday, every month' */ 
OR (r.rectypeid >= 37 AND r.day = d.dow and r.islast = d.islast) 
LEFT JOIN events e on e.rectypeid = r.rectypeid OR (e.rectypeid <= 1 AND e.eventid IS NOT NULL) 
LEFT JOIN eventtypes t ON e.eventtypeid = t.eventtypeid 
LEFT JOIN names n ON e.namesid = n.namesid 
WHERE (d.dt BETWEEN '2012/02/01' AND '2012/05/01') 
ORDER BY d.dt; 
+0

शानदार, लगभग! यह बहुत अच्छा है और वस्तुतः वहां है, लेकिन यह घटनाओं के दौरान भी पंक्तियों को दोहराता है। Rightypeid = 1 (कोई पुनरावृत्ति नहीं), शायद क्योंकि घटना और पुनरावर्ती सारणी सिंक से बाहर हो जाती है? मुझे संदेह है कि आपके 'या' के बाद 'गायब' हो सकता है लेकिन मैं नहीं सोच सकता कि यह क्या होना चाहिए। – blankabout

+0

@blankabout: स्थिति कम या बराबर है लेकिन शायद यह क्वेरी हल हो सकती है: या (e.rectypeid <= 1 और e.eventid पूर्ण नहीं है)। अन्यथा मैं e.rectypeid <1 कोशिश करूँगा? या आप e.eventid को कहां जोड़ सकते हैं जहां खंड नहीं है? यह सस्ता है। – Bytemain

+0

अफसोस की बात है कि उन विकल्पों में से कोई भी मदद नहीं की। मुझे आश्चर्य है कि क्या एक अलग दृष्टिकोण मदद करेगा, शायद दो प्रश्नों के संघ का कुछ प्रकार, हालांकि यूनियनों के मेरे (सीमित) अनुभव से पता चलता है कि वे एक विशेष रूप से उपयोगी तरीके से एक साथ वेल्डेड केवल दो पूरी तरह अलग प्रश्न हैं। – blankabout

संबंधित मुद्दे