Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

अगली घटना तिथि प्रदर्शित करें

आपका पहला कदम यह है कि आप प्रत्येक ईवेंट के साथ अपना ईवेंट प्रारंभ दिनांक प्राप्त करें, और दोहराव अंतराल, ऐसा करने के लिए आप इसका उपयोग कर सकते हैं:

SELECT  EventID = e.ID, 
        e.Name, 
        StartDateTime = DATEADD(SECOND, rs.Meta_Value, '19700101'),
        RepeatInterval = ri.Meta_Value
FROM    dbo.Events e
        INNER JOIN dbo.Events_Meta rs
            ON rs.Event_ID = e.ID
            AND rs.Meta_Key = 'repeat_start'
        INNER JOIN dbo.Events_Meta ri
            ON ri.Event_ID = e.ID
            AND ri.Meta_Key = 'repeat_interval_' + CAST(e.ID AS VARCHAR(10));

यह देता है:

EventID | Name         | StartDateTime       | RepeatInterval
--------+--------------+---------------------+-----------------
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800
   1    | Billa Vist   | 2014-01-04 18:00:00 |     604800

इसे दोहराने के लिए आपको क्रॉस जॉइन करने के लिए एक नंबर टेबल की आवश्यकता होगी, यदि आपके पास एक नहीं है तो फ्लाई पर एक उत्पन्न करने के कई तरीके हैं, सरल कारणों से मैं इसका उपयोग करूंगा:

WITH Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
)
SELECT  Number
FROM    Numbers;

आगे पढ़ने के लिए, आरोन बर्ट्रेंड ने संख्याओं की अनुक्रमिक सूचियाँ बनाने के तरीकों की गहराई से तुलना की है:

  • लूप के बिना एक सेट या अनुक्रम उत्पन्न करें - part1
  • लूप के बिना एक सेट या अनुक्रम उत्पन्न करें - part2
  • बिना लूप के एक सेट या अनुक्रम जेनरेट करें - part3

यदि हम अपनी संख्या तालिका को केवल 0 - 5 तक सीमित रखते हैं, और केवल पहली घटना को देखते हैं, तो दोनों को क्रॉस जॉइन करने से निम्न मिलेगा:

EventID | Name         | StartDateTime       | RepeatInterval | Number
--------+--------------+---------------------+----------------+---------
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    0
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    1
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    2
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    3
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    4
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    5

फिर आप RepeatInterval * Number . जोड़कर अपना मौका पा सकते हैं घटना शुरू होने के समय के लिए:

DECLARE @EndDate DATETIME = '20140130';

WITH EventData AS
(   SELECT  EventID = e.ID, 
            e.Name, 
            StartDateTime = DATEADD(SECOND, rs.Meta_Value, '19700101'),
            RepeatInterval = ri.Meta_Value
    FROM    dbo.Events e
            INNER JOIN dbo.Events_Meta rs
                ON rs.Event_ID = e.ID
                AND rs.Meta_Key = 'repeat_start'
            INNER JOIN dbo.Events_Meta ri
                ON ri.Event_ID = e.ID
                AND ri.Meta_Key = 'repeat_interval_' + CAST(rs.ID AS VARCHAR(10))
), Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
)
SELECT  e.EventID,
        e.Name,
        EventDate = DATEADD(SECOND, n.Number * e.RepeatInterval, e.StartDateTime)
FROM    EventData e
        CROSS JOIN Numbers n
WHERE   DATEADD(SECOND, n.Number * e.RepeatInterval, e.StartDateTime) < @EndDate
ORDER BY e.EventID, EventDate;

यह आपका अपेक्षित आउटपुट देता है:

EVENTID | NAME          | EVENTDATE
--------+---------------+--------------------------------
   1    | Billa Vist    | January, 03 2014 10:00:00+0000
   1    | Billa Vist    | January, 04 2014 18:00:00+0000
   1    | Billa Vist    | January, 10 2014 10:00:00+0000
   1    | Billa Vist    | January, 11 2014 18:00:00+0000
   1    | Billa Vist    | January, 17 2014 10:00:00+0000
   1    | Billa Vist    | January, 18 2014 18:00:00+0000
   1    | Billa Vist    | January, 24 2014 10:00:00+0000
   1    | Billa Vist    | January, 25 2014 18:00:00+0000

SQL Fiddle पर उदाहरण

मुझे लगता है कि आपके पास जो स्कीमा है वह संदिग्ध है, हालांकि इसमें शामिल हों:

Meta_Key = 'repeat_interval_' + CAST(rs.ID AS VARCHAR(10))

सबसे अच्छा तुच्छ है। मुझे लगता है कि बेहतर होगा कि आप आरंभ तिथि और उससे जुड़े अंतराल को एक साथ संगृहीत करें:

CREATE TABLE dbo.Events_Meta
(       ID INT IDENTITY(1, 1) NOT NULL,
        Event_ID INT NOT NULL,
        StartDateTime DATETIME2 NOT NULL,
        IntervalRepeat INT NULL, -- NULLABLE FOR SINGLE EVENTS
        RepeatEndDate DATETIME2 NULL, -- NULLABLE FOR EVENTS THAT NEVER END
    CONSTRAINT PK_Events_Meta__ID PRIMARY KEY (ID),
    CONSTRAINT FK_Events_Meta__Event_ID FOREIGN KEY (Event_ID) REFERENCES dbo.Events (ID)
);

यह आपके डेटा को सरल बना देगा:

EventID | StartDateTime       | RepeatInterval | RepeatEndDate
--------+---------------------+----------------+---------------
   1    | 2014-01-03 10:00:00 |    604800      |     NULL
   1    | 2014-01-04 18:00:00 |    604800      |     NULL

यह आपको अपने दोहराने के लिए एक समाप्ति तिथि जोड़ने की अनुमति देता है, अर्थात यदि आप इसे केवल एक सप्ताह के लिए दोहराना चाहते हैं। इसके बाद आपकी क्वेरी सरल हो जाती है:

DECLARE @EndDate DATETIME = '20140130';
WITH Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
)
SELECT  e.ID,
        e.Name,
        EventDate = DATEADD(SECOND, n.Number * em.IntervalRepeat, em.StartDateTime) 
FROM    Events e
        INNER JOIN Events_Meta em
            ON em.Event_ID = e.ID
        CROSS JOIN Numbers n
WHERE   DATEADD(SECOND, n.Number * em.IntervalRepeat, em.StartDateTime) <= @EndDate
AND (   DATEADD(SECOND, n.Number * em.IntervalRepeat, em.StartDateTime) <= em.RepeatEndDate 
    OR  em.RepeatEndDate IS NULL
    )
ORDER BY EventDate;

SQL Fiddle पर उदाहरण

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

उपरोक्त ईआर रिपीटएवेंट में आवर्ती घटना के लिए बुनियादी जानकारी संग्रहीत होती है, फिर दोहराने के प्रकार (दैनिक, साप्ताहिक, मासिक) के आधार पर एक या अधिक अन्य तालिकाओं को पॉप्युलेट किया जाता है। साप्ताहिक ईवेंट के उदाहरण में, यह सप्ताह के उन सभी दिनों को संग्रहीत करेगा, जिन्हें वह RepeatDay तालिका में दोहराता है . यदि इसे केवल कुछ महीनों तक सीमित रखने की आवश्यकता है, तो आप इन महीनों को RepeatMonth में संग्रहीत कर सकते हैं , और इसी तरह।

फिर कैलेंडर तालिका का उपयोग करके आप पहली तारीख के बाद सभी संभावित तिथियां प्राप्त कर सकते हैं, और इन्हें केवल उन तिथियों तक सीमित कर सकते हैं जो वर्ष के सप्ताह/माह के दिन से मेल खाते हैं:

WITH RepeatingEvents AS
(   SELECT  e.Name,
            re.StartDateTime,
            re.EndDateTime,
            re.TimesToRepeat,
            RepeatEventDate = CAST(c.DateKey AS DATETIME) + CAST(re.StartTime AS DATETIME),
            RepeatNumber = ROW_NUMBER() OVER(PARTITION BY re.RepeatEventID ORDER BY c.Datekey)
    FROM    dbo.Event e
            INNER JOIN dbo.RepeatEvent re
                ON e.EventID = re.EventID
            INNER JOIN dbo.RepeatType rt
                ON rt.RepeatTypeID = re.RepeatTypeID
            INNER JOIN dbo.Calendar c
                ON c.DateKey >= re.StartDate
            INNER JOIN dbo.RepeatDayOfWeek rdw
                ON rdw.RepeatEventID = re.RepeatEventID
                AND rdw.DayNumberOfWeek = c.DayNumberOfWeek
    WHERE   rt.Name = 'Weekly'
)
SELECT  Name, StartDateTime, RepeatEventDate, RepeatNumber
FROM    RepeatingEvents
WHERE   (TimesToRepeat IS NULL OR RepeatNumber <= TimesToRepeat)
AND     (EndDateTime IS NULL OR RepeatEventDate <= EndDateTime);

SQL Fiddle पर उदाहरण

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर में कस्टम दिनांक/समय स्वरूपण

  2. sql सर्वर अमान्य वस्तु का नाम - लेकिन तालिकाएँ SSMS तालिका सूची में सूचीबद्ध हैं

  3. SQL सर्वर में दिनांक और समय के लिए ODBC स्केलर फ़ंक्शंस (T-SQL उदाहरण)

  4. दो तिथियों के बीच SQL समय अंतर hh:mm:ss . में परिणाम देता है

  5. अटैचडबफाइलनाम के साथ क्या समस्या है?