दो तिथियों के बीच तारीखों की एक सूची प्राप्त करें


91

मानक mysql फ़ंक्शन का उपयोग करना क्वेरी लिखने का एक तरीका है जो दो तिथियों के बीच दिनों की सूची लौटाएगा।

उदाहरण के लिए 2009-01-01 और 2009-01-13 को दिए गए मानों के साथ यह एक कॉलम तालिका लौटाएगा:

 2009-01-01 
 2009-01-02 
 2009-01-03
 2009-01-04 
 2009-01-05
 2009-01-06
 2009-01-07
 2009-01-08 
 2009-01-09
 2009-01-10
 2009-01-11
 2009-01-12
 2009-01-13

संपादित करें: ऐसा प्रतीत होता है कि मैं स्पष्ट नहीं हूं। मैं इस सूची को जनरेट करना चाहता हूं। मेरे पास डेटाबेस (डेटाटाइम द्वारा) में संग्रहीत मान हैं, लेकिन उन्हें उपरोक्त तारीखों की सूची में शामिल होने के लिए बाईं ओर बाहरी रूप से एकत्र किया जाना चाहिए (मैं इनमें से कुछ के दाईं ओर से अशक्त होने की उम्मीद कर रहा हूं और कुछ दिनों तक इसे संभाल लूंगा )।


2
मैं सबसे अच्छा समाधान जवाब में वर्णन किया गया लगता है stackoverflow.com/a/2157776/466677
मारेक ग्रेगर

जवाबों:


68

मैं इस संग्रहीत कार्यविधि का उपयोग करने के लिए अंतराल की जरूरत उत्पन्न करने के लिए अस्थायी सारणी में time_intervals , तो JOIN और अपनी डेटा तालिका को temp time_intervals table के साथ संयोजित करें ।

प्रक्रिया आपके द्वारा निर्दिष्ट सभी विभिन्न प्रकारों के अंतराल उत्पन्न कर सकती है:

call make_intervals('2009-01-01 00:00:00','2009-01-10 00:00:00',1,'DAY')
.
select * from time_intervals  
.
interval_start      interval_end        
------------------- ------------------- 
2009-01-01 00:00:00 2009-01-01 23:59:59 
2009-01-02 00:00:00 2009-01-02 23:59:59 
2009-01-03 00:00:00 2009-01-03 23:59:59 
2009-01-04 00:00:00 2009-01-04 23:59:59 
2009-01-05 00:00:00 2009-01-05 23:59:59 
2009-01-06 00:00:00 2009-01-06 23:59:59 
2009-01-07 00:00:00 2009-01-07 23:59:59 
2009-01-08 00:00:00 2009-01-08 23:59:59 
2009-01-09 00:00:00 2009-01-09 23:59:59 
.
call make_intervals('2009-01-01 00:00:00','2009-01-01 02:00:00',10,'MINUTE')
. 
select * from time_intervals
.  
interval_start      interval_end        
------------------- ------------------- 
2009-01-01 00:00:00 2009-01-01 00:09:59 
2009-01-01 00:10:00 2009-01-01 00:19:59 
2009-01-01 00:20:00 2009-01-01 00:29:59 
2009-01-01 00:30:00 2009-01-01 00:39:59 
2009-01-01 00:40:00 2009-01-01 00:49:59 
2009-01-01 00:50:00 2009-01-01 00:59:59 
2009-01-01 01:00:00 2009-01-01 01:09:59 
2009-01-01 01:10:00 2009-01-01 01:19:59 
2009-01-01 01:20:00 2009-01-01 01:29:59 
2009-01-01 01:30:00 2009-01-01 01:39:59 
2009-01-01 01:40:00 2009-01-01 01:49:59 
2009-01-01 01:50:00 2009-01-01 01:59:59 
.
I specified an interval_start and interval_end so you can aggregate the 
data timestamps with a "between interval_start and interval_end" type of JOIN.
.
Code for the proc:
.
-- drop procedure make_intervals
.
CREATE PROCEDURE make_intervals(startdate timestamp, enddate timestamp, intval integer, unitval varchar(10))
BEGIN
-- *************************************************************************
-- Procedure: make_intervals()
--    Author: Ron Savage
--      Date: 02/03/2009
--
-- Description:
-- This procedure creates a temporary table named time_intervals with the
-- interval_start and interval_end fields specifed from the startdate and
-- enddate arguments, at intervals of intval (unitval) size.
-- *************************************************************************
   declare thisDate timestamp;
   declare nextDate timestamp;
   set thisDate = startdate;

   -- *************************************************************************
   -- Drop / create the temp table
   -- *************************************************************************
   drop temporary table if exists time_intervals;
   create temporary table if not exists time_intervals
      (
      interval_start timestamp,
      interval_end timestamp
      );

   -- *************************************************************************
   -- Loop through the startdate adding each intval interval until enddate
   -- *************************************************************************
   repeat
      select
         case unitval
            when 'MICROSECOND' then timestampadd(MICROSECOND, intval, thisDate)
            when 'SECOND'      then timestampadd(SECOND, intval, thisDate)
            when 'MINUTE'      then timestampadd(MINUTE, intval, thisDate)
            when 'HOUR'        then timestampadd(HOUR, intval, thisDate)
            when 'DAY'         then timestampadd(DAY, intval, thisDate)
            when 'WEEK'        then timestampadd(WEEK, intval, thisDate)
            when 'MONTH'       then timestampadd(MONTH, intval, thisDate)
            when 'QUARTER'     then timestampadd(QUARTER, intval, thisDate)
            when 'YEAR'        then timestampadd(YEAR, intval, thisDate)
         end into nextDate;

      insert into time_intervals select thisDate, timestampadd(MICROSECOND, -1, nextDate);
      set thisDate = nextDate;
   until thisDate >= enddate
   end repeat;

 END;

इस पोस्ट के निचले भाग में समान उदाहरण डेटा परिदृश्य , जहाँ मैंने SQL सर्वर के लिए एक समान फ़ंक्शन बनाया था।


4
मैं व्यक्तिगत रूप से PostgreSQL में उत्पन्न दृश्यों के समान कुछ के लिए उम्मीद कर रहा था।
फिलिप व्हेलन

यदि आप एक बार डेटा उत्पन्न कर रहे हैं, तो आप स्थायी तालिका का उपयोग भी कर सकते हैं और लापता तारीखों को भरने के लिए इस स्क्रिप्ट का उपयोग कर सकते हैं।
बिमल पौडेल

मुझे phpMyAdmin के माध्यम से काम करने के लिए बनाने की प्रक्रिया के बयान से पहले सीमांकक को बदलना था (घोषित बयानों पर वाक्यविन्यास त्रुटि से बचने के लिए) [कोड] DECLARE // [/ कोड]
Defkon1

यह समाधान बहुत शक्तिशाली और लचीला है, दुर्भाग्य से mariaDB पर मुझे त्रुटि # 1067 मिल रही है - कॉल मेक इन्टरवेनल ('2009-01-01 00:00:00', '2009-01-10) को चलाने के दौरान' अंतराल 'के लिए अमान्य डिफ़ॉल्ट मान। 00: 00: 00 ', 1,' दिन '); मैं संस्करण ५. am.२ira पर है
शेल्बीपेरेरा

28

MSSQL के लिए आप इसका उपयोग कर सकते हैं। यह बहुत जल्दी है।

आप इसे एक टेबल वैल्यू फंक्शन या स्टोरेड प्रॉप में लपेट सकते हैं और वेरिएबल्स के रूप में स्टार्ट और एंड डेट्स में पार्स कर सकते हैं।

DECLARE @startDate DATETIME
DECLARE @endDate DATETIME

SET @startDate = '2011-01-01'
SET @endDate = '2011-01-31';

WITH dates(Date) AS 
(
    SELECT @startdate as Date
    UNION ALL
    SELECT DATEADD(d,1,[Date])
    FROM dates 
    WHERE DATE < @enddate
)

SELECT Date
FROM dates
OPTION (MAXRECURSION 0)
GO

2
यहाँ OPTION (MAXRECURSION 0) का उपयोग क्या है?
शिव

14

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

हमारे पास एक नौकरी है जो यह सुनिश्चित करने के लिए हर महीने चलती है कि तालिका भविष्य में 5 साल से बाहर है। तालिका इस प्रकार बनाई गई है:

create table all_dates (
    dt date primary key
);

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

अन्य विकल्प (और हमने पहले भी इसका उपयोग किया है) यह सुनिश्चित करना है कि हर तारीख के लिए तालिका में एक प्रविष्टि है। हमने समय-समय पर तालिका तैराई और तारीखों और / या समय के लिए शून्य प्रविष्टियाँ जोड़ीं जो अस्तित्व में नहीं थीं। यह आपके मामले में एक विकल्प नहीं हो सकता है, यह संग्रहीत डेटा पर निर्भर करता है।

यदि आप वास्तव में सोचते हैं कि यह रखने के लिए एक परेशानी हैall_dates टेबल को आबाद , तो एक संग्रहीत प्रक्रिया वह रास्ता है जो उन तिथियों वाले डेटासेट को लौटाएगा। यह लगभग निश्चित रूप से धीमा होगा क्योंकि आपको हर बार किसी तालिका से पूर्व-परिकलित डेटा को खींचने के बजाए रेंज की गणना करना होगा।

लेकिन, ईमानदार होने के लिए, आप किसी भी गंभीर डेटा स्टोरेज की समस्याओं के बिना 1000 वर्षों के लिए टेबल को पॉप्युलेट कर सकते हैं - 365,000 16-बाइट (उदाहरण के लिए) तारीखों के साथ साथ एक इंडेक्स डेट को प्लस करने के लिए सुरक्षा के लिए 20% ओवरहेड, मैं मोटे तौर पर अनुमान लगाता हूं 14M के बारे में [365,000 * 16 * 2 * 1.2 = 14,016,000 बाइट्स]), चीजों की योजना में एक मामूली तालिका।


12

आप इस तरह MySQL के उपयोगकर्ता चर का उपयोग कर सकते हैं :

SET @num = -1;
SELECT DATE_ADD( '2009-01-01', interval @num := @num+1 day) AS date_sequence, 
your_table.* FROM your_table
WHERE your_table.other_column IS NOT NULL
HAVING DATE_ADD('2009-01-01', interval @num day) <= '2009-01-13'

@num -1 है क्योंकि आप इसे पहली बार जोड़ते हैं जब आप इसका उपयोग करते हैं। इसके अलावा, आप "HAVING date_fterence" का उपयोग नहीं कर सकते क्योंकि यह प्रत्येक पंक्ति के लिए उपयोगकर्ता चर में दो बार वृद्धि करता है।


8

इस उत्तर से एक विचार उधार लेते हुए , आप 9 के माध्यम से 0 के साथ एक टेबल सेट कर सकते हैं और अपनी तिथियों की सूची तैयार करने के लिए इसका उपयोग कर सकते हैं।

CREATE TABLE num (i int);
INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);

select adddate('2009-01-01', numlist.id) as `date` from
(SELECT n1.i + n10.i*10 + n100.i*100 AS id
   FROM num n1 cross join num as n10 cross join num as n100) as numlist
where adddate('2009-01-01', numlist.id) <= '2009-01-13';

इससे आप 1000 तारीख तक की सूची तैयार कर सकेंगे। यदि आपको बड़ा जाने की आवश्यकता है, तो आप आंतरिक क्वेरी में एक और क्रॉस जोड़ सकते हैं।


यह समाधान काफी बेहतर काम करता है। लेकिन इसका UNIX_TIMESTAMP () के साथ एक मुद्दा है - यह 1231185600.000000 जैसे परिणाम देता है; दशमलव बिंदु के बाद मिलिससेकंड भाग; जबकि - SELECT UNIX_TIMESTAMP (ADDDATE ('2009-01-01', 0)) AS date; उस भाग का परिणाम नहीं है।
बिमल पौडेल

3

एक्सेस (या किसी SQL भाषा) के लिए

  1. एक तालिका बनाएं जिसमें 2 फ़ील्ड हैं, हम इस तालिका को कॉल करेंगे tempRunDates: -
    फ़ील्ड fromDateऔर toDate
    - जब केवल 1 रिकॉर्ड सम्मिलित करें, जिसमें प्रारंभ दिनांक और अंतिम तिथि हो।

  2. एक और तालिका बनाएं: Time_Day_Ref
    - इस तालिका में तारीखों की सूची बनाएं (एक्सेल में सूची बनाना आसान है)।
    - मेरे मामले में क्षेत्र का नाम है Greg_Dt, ग्रेगोरियन तिथि के लिए
    - मैंने 1 जून 2009 से 1 जून 2020 तक मेरी सूची बनाई।

  3. क्वेरी चलाएँ:

    SELECT Time_Day_Ref.GREG_DT
    FROM tempRunDates, Time_Day_Ref
    WHERE Time_Day_Ref.greg_dt>=tempRunDates.fromDate And greg_dt<=tempRunDates.toDate;

आसान!


2

आमतौर पर कोई एक सहायक संख्या तालिका का उपयोग करेगा जिसे आप आमतौर पर इस उद्देश्य के लिए इस पर कुछ भिन्नता के साथ रखते हैं:

SELECT *
FROM (
    SELECT DATEADD(d, number - 1, '2009-01-01') AS dt
    FROM Numbers
    WHERE number BETWEEN 1 AND DATEDIFF(d, '2009-01-01', '2009-01-13') + 1
) AS DateRange
LEFT JOIN YourStuff
    ON DateRange.dt = YourStuff.DateColumn

मैंने तालिका-मूल्यवान कार्यों आदि के साथ विभिन्नताएं देखी हैं।

आप तिथियों की एक स्थायी सूची भी रख सकते हैं। हमारे पास हमारे डेटा वेयरहाउस के साथ-साथ दिन के समय की सूची है।


2

खैर SQL सर्वर में दो दी गई तारीख के बीच की तारीखों का पता कैसे लगाया जाए http://ektaraval.blogspot.com/2010/09/writing-recursive-query-to-find-out-all.html


1
MySQL अभी तक पुनरावर्ती प्रश्नों का समर्थन नहीं करता है, इसलिए इस समाधान का उपयोग यहां नहीं किया जा सकता है।
मार्क बायर्स

2
CREATE FUNCTION [dbo].[_DATES]
(
    @startDate DATETIME,
    @endDate DATETIME
)
RETURNS 
@DATES TABLE(
    DATE1 DATETIME
)
AS
BEGIN
    WHILE @startDate <= @endDate
    BEGIN 
        INSERT INTO @DATES (DATE1)
            SELECT @startDate   
    SELECT @startDate = DATEADD(d,1,@startDate) 
    END
RETURN
END

2

मारियाडीबी> = 10.3 और MySQL> = 8.0 में नए पुनरावर्ती (कॉमन टेबल एक्सप्रेशंस) कार्यक्षमता का उपयोग करके सुरुचिपूर्ण समाधान।

WITH RECURSIVE t as (
    select '2019-01-01' as dt
  UNION
    SELECT DATE_ADD(t.dt, INTERVAL 1 DAY) FROM t WHERE DATE_ADD(t.dt, INTERVAL 1 DAY) <= '2019-04-30'
)
select * FROM t;

उपरोक्त '2019-01-01' और '2019-04-30' के बीच की तारीखों की एक तालिका देता है।


"चयन 2019-01-01 'को dt के रूप में चुनें" यह चयनकर्ता क्या है? क्या यह केवल एक से और क्षेत्र का चयन करना संभव है?
मिगुएल स्टीवंस

1

हमने अपने HRMS सिस्टम में इसका उपयोग किया है

SELECT CAST(DAYNAME(daydate) as CHAR) as dayname,daydate
    FROM
    (select CAST((date_add('20110101', interval H.i*100 + T.i*10 + U.i day) )as DATE) as daydate
      from erp_integers as H
    cross
      join erp_integers as T
    cross
      join erp_integers as U
     where date_add('20110101', interval H.i*100 + T.i*10 + U.i day ) <= '20110228'
    order
        by daydate ASC
        )Days

1

यह समाधान MySQL 5.0 के साथ काम कर रहा है
- एक तालिका बनाएं - mytable
स्कीमा में सामग्री नहीं है। क्या मायने रखता है इसमें पंक्तियों की संख्या।
तो, आप 10 पंक्तियों, मानों - 1 से 10 के साथ INT का केवल एक कॉलम टाइप कर सकते हैं।

एसक्यूएल:

set @tempDate=date('2011-07-01') - interval 1 day;
select
date(@tempDate := (date(@tempDate) + interval 1 day)) as theDate
from mytable x,mytable y
group by theDate
having theDate <= '2011-07-31';

सीमा: उपरोक्त क्वेरी द्वारा लौटाए गए दिनांक की अधिकतम संख्या होगी
(rows in mytable)*(rows in mytable) = 10*10 = 100.

आप sql में फॉर्म पार्ट को बदलकर इस रेंज को बढ़ा सकते हैं:
mytable x, mytable y, mytable z
So से, रेंज हो 10*10*10 =1000और इसी तरह।


0

एक संग्रहीत कार्यविधि बनाएं जो दो पैरामीटर a_begin और a_end लेता है। इसके भीतर एक अस्थायी तालिका बनाएँ, जिसे t कहा जाता है, एक चर d घोषित करें, a_begin को d असाइन करें, और d में वृद्धि करने के लिए t और कॉलिंग फ़ंक्शन में d WHILEलूप INSERTing चलाएँ ADDDATE। अंत में SELECT * FROM t


वास्तव में मेरा मानना ​​है कि निष्पादन की गति के लिए एक स्थायी तालिका बेहतर होगी (न्यूनतम भंडारण आवश्यकताएं हैं)। हर बार जब आपको उनकी आवश्यकता होती है, तो रेंज बनाने की तुलना में, तालिका में तारीखों को पूर्व-गणना करना और निकालना आवश्यक है।
paxdiablo

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

@ eed3si9n, समय से पहले अनुकूलन, हाँ, सभी अनुकूलन नहीं :-) यदि आपका उदाहरण सही था, तो हाँ, मैं आपसे सहमत हूँ, लेकिन इसे निश्चितता के लिए मापा जाना चाहिए। जैसा कि मैंने सुझाव दिया था 1000 सारणी (एक बार की लागत) उत्पन्न करने पर टेबल मेन्ट हो गया है, लेकिन वे सेकंड जोड़ देंगे।
पैक्साडब्लो

0

मैं इसके समान कुछ उपयोग करूंगा:

DECLARE @DATEFROM AS DATETIME
DECLARE @DATETO AS DATETIME
DECLARE @HOLDER TABLE(DATE DATETIME)

SET @DATEFROM = '2010-08-10'
SET @DATETO = '2010-09-11'

INSERT INTO
    @HOLDER
        (DATE)
VALUES
    (@DATEFROM)

WHILE @DATEFROM < @DATETO
BEGIN

    SELECT @DATEFROM = DATEADD(D, 1, @DATEFROM)
    INSERT 
    INTO
        @HOLDER
            (DATE)
    VALUES
        (@DATEFROM)
END

SELECT 
    DATE
FROM
    @HOLDER

तब @HOLDERचर तालिका उन सभी तिथियों के बीच दिन-प्रतिदिन बढ़ती गई सभी तिथियों को आपके दिल की सामग्री में शामिल होने के लिए तैयार रखती है।


हैलो, मैं कोड का उपयोग करने की कोशिश कर रहा हूं और आउटपुट को एक तालिका में सम्मिलित कर रहा हूं मैंने DateTest को स्तंभ डेटफल के प्रकार DATETIME के ​​साथ परिभाषित किया ... लेकिन असफल रहा ... क्या आप उस कोड को प्रदान कर सकते हैं जो उस के साथ काम करेगा? नोट: यहाँ SQL सर्वर का उपयोग कर धन्यवाद :)
sys_debug

0

मैं इसके साथ काफी समय से लड़ रहा हूं। चूंकि यह Google पर पहली हिट है जब मैंने समाधान के लिए खोज की, मुझे पोस्ट करें जहां मैंने अभी तक प्राप्त किया है।

SET @d := '2011-09-01';
SELECT @d AS d, cast( @d := DATE_ADD( @d , INTERVAL 1 DAY ) AS DATE ) AS new_d
  FROM [yourTable]
  WHERE @d <= '2012-05-01';

[yourTable]अपने डेटाबेस से तालिका के साथ बदलें । चाल यह है कि आपके द्वारा चुनी गई तालिका में पंक्तियों की संख्या> = आप कितनी तारीखों को वापस करना चाहते हैं। मैंने टेबल प्लेसहोल्डर DUAL का उपयोग करने की कोशिश की, लेकिन यह केवल एक ही पंक्ति को लौटाएगा।


1
दिलचस्प दृष्टिकोण। लेकिन .. क्या यह अनिवार्य रूप से विहंग ने ऊपर सुझाया नहीं है?)
लेह

0
select * from table_name where col_Date between '2011/02/25' AND DATEADD(s,-1,DATEADD(d,1,'2011/02/27'))

यहां, पहले दिन को वर्तमान एंडेट में जोड़ें, यह 2011-02-28 00:00:00 होगा, फिर आप अंतिम तिथि 2011-02-27 23:59:59 बनाने के लिए एक सेकंड घटाते हैं। ऐसा करने से, आप दिए गए अंतराल के बीच सभी तिथियां प्राप्त कर सकते हैं।

आउटपुट:
2011/02/25
2011/02/26
2011/02/27


0
DELIMITER $$  
CREATE PROCEDURE popula_calendario_controle()
   BEGIN
      DECLARE a INT Default 0;
      DECLARE first_day_of_year DATE;
      set first_day_of_year = CONCAT(DATE_FORMAT(curdate(),'%Y'),'-01-01');
      one_by_one: LOOP
         IF dayofweek(adddate(first_day_of_year,a)) <> 1 THEN
            INSERT INTO calendario.controle VALUES(null,150,adddate(first_day_of_year,a),adddate(first_day_of_year,a),1);
         END IF;
         SET a=a+1;
         IF a=365 THEN
            LEAVE one_by_one;
         END IF;
      END LOOP one_by_one;
END $$

यह प्रक्रिया वर्ष की शुरुआत से लेकर अब तक की सभी तिथियों को सम्मिलित करेगी, बस "प्रारंभ" और "अंत" के दिनों को प्रतिस्थापित करें, और आप जाने के लिए तैयार हैं!


IF a=365 THENलीप वर्षों से कैसे प्रभावित होती है रेखा ?
स्टीवर्ट

इसके अलावा, 150लाइन 9 पर संख्या का क्या महत्व है ? यह कोड बहुत वास्तविक स्पष्टीकरण के बिना एक "पैट जवाब" है।
स्टीवर्ट

0

मुझे आँकड़ों के लिए 2 तारीखों के बीच सभी महीनों के साथ एक सूची चाहिए। 2 तिथियां एक सदस्यता से प्रारंभ और समाप्ति हैं। इसलिए सूची सभी महीनों और प्रति माह सदस्यता की मात्रा को दिखाती है।

माई एसक्यूएल

CREATE PROCEDURE `get_amount_subscription_per_month`()
BEGIN
   -- Select the ultimate start and enddate from subscribers
   select @startdate := min(DATE_FORMAT(a.startdate, "%Y-%m-01")), 
          @enddate := max(DATE_FORMAT(a.enddate, "%Y-%m-01")) + interval 1 MONTH
   from subscription a;

   -- Tmp table with all months (dates), you can always format them with DATE_FORMAT) 
   DROP TABLE IF EXISTS tmp_months;
   create temporary table tmp_months (
      year_month date,
      PRIMARY KEY (year_month)
   );


   set @tempDate=@startdate;  #- interval 1 MONTH;

   -- Insert every month in tmp table
   WHILE @tempDate <= @enddate DO
     insert into tmp_months (year_month) values (@tempDate);
     set @tempDate = (date(@tempDate) + interval 1 MONTH);
   END WHILE;

   -- All months
   select year_month from tmp_months;

   -- If you want the amount of subscription per month else leave it out
   select mnd.year_month, sum(subscription.amount) as subscription_amount
   from tmp_months mnd
   LEFT JOIN subscription ON mnd.year_month >= DATE_FORMAT(subscription.startdate, "%Y-%m-01") and mnd.year_month <= DATE_FORMAT(subscription.enddate, "%Y-%m-01")
   GROUP BY mnd.year_month;

 END

0

आप इसका उपयोग कर सकते हैं

SELECT CAST(cal.date_list AS DATE) day_year
FROM (
  SELECT SUBDATE('2019-01-01', INTERVAL 1 YEAR) + INTERVAL xc DAY AS date_list
  FROM (
        SELECT @xi:=@xi+1 as xc from
        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc1,
        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc2,
        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc3,
        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc4,
        (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc5,
        (SELECT @xi:=-1) xc0
    ) xxc1
) cal
WHERE cal.date_list BETWEEN '2019-01-01' AND '2019-12-31'
ORDER BY cal.date_list DESC;

स्रोत: - shayanderson.com/mysql/…
Dixon 15

-2

मै इस्तेमाल कर रहा हूँ Server version: 5.7.11-log MySQL Community Server (GPL)

अब हम इसे सरल तरीके से हल करेंगे।

मैंने "datetable" नाम की एक तालिका बनाई है

mysql> describe datetable;
+---------+---------+------+-----+---------+-------+
| Field   | Type    | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| colid   | int(11) | NO   | PRI | NULL    |       |
| coldate | date    | YES  |     | NULL    |       |
+---------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

अब, हम सम्मिलित किए गए रिकॉर्ड देखेंगे।

mysql> select * from datetable;
+-------+------------+
| colid | coldate    |
+-------+------------+
|   101 | 2015-01-01 |
|   102 | 2015-05-01 |
|   103 | 2016-01-01 |
+-------+------------+
3 rows in set (0.00 sec)

और यहाँ उन तिथियों के बजाय दो तिथियों के भीतर रिकॉर्ड लाने के लिए हमारी क्वेरी है।

mysql> select * from datetable where coldate > '2015-01-01' and coldate < '2016-01-01';
+-------+------------+
| colid | coldate    |
+-------+------------+
|   102 | 2015-05-01 |
+-------+------------+
1 row in set (0.00 sec)

उम्मीद है कि यह कई लोगों की मदद करेगा।


बिना किसी कारण के, यह एसक्यूएल ठीक है और काम के परिदृश्य में है।
आरिफ़मुस्तफा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.