Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL: Getting the period start and end datetimes from data like this? Tricky little puzzle I'm struggling with

I have a table which lists every date within the year. Each row also contains a period number from 1 to 13 which loop around each year. It looks something like this:

|        Date         | Period |
| 2012-12-27 00:00:00 |   12   |
| 2012-12-28 00:00:00 |   12   |
| 2012-12-29 00:00:00 |   13   |
| 2012-12-30 00:00:00 |   13   |
| 2012-12-31 00:00:00 |   13   |
| 2013-01-01 00:00:00 |   13   |
| 2013-01-02 00:00:00 |   13   |
|        . . .        |   13   | 
| 2013-02-10 00:00:00 |   01   |
|        . . .        |   01   | 
| 2013-03-14 00:00:00 |   02   |
|        . . .        |   02   | 
| 2013-05-05 00:00:00 |   03   |

As you can see above, period 13 starts on the 29th of dec 2012 and finishes on the 09th of Febuary 2013. I work this out by getting the first and last dates for period 13.

I need to write a query that will get the period start and end dates for the current period. But I'm having problems because the periods sometimes occur twice a year and sometimes overlap between the years like this example does.

A few more examples:

If getDate() = '2013-02-25 13:45:00' then the period should be 01 and the start and end dates would be '2013-02-10 00:00:00' and '2013-03-14 00:00:00'

If getDate() = '2013-03-15 00:00:00' then the period should be 02 and the start and end dates would be '2013-03-14 00:00:00' and '2013-05-05 00:00:00'

I really hope this makes sense. Let me know if I need to clarify it! Thanks for your help :)

like image 733
user1636130 Avatar asked Jan 04 '13 14:01

user1636130


People also ask

How do I get the start date and end date in SQL?

To use the dateadd function in SQL, we need to use the SELECT query followed by the DATEDIFF function and then return the output. The datePart should be provided only valid input (Check valid input table for datePart) and the startDate and the endDate should be provided with a date input in a proper format.

How can I get month start and end date in SQL?

Syntax : = EOMONTH(start_date, months) EOMONTH takes 2 parameters, first as StartDate and next as month travels from that start date, and then outputs the last day of that month. If we set parameter months as 0, then EOMONTH will output the last day of the month in which StartDate falls.

How can I get data between specific dates in SQL?

Query: SELECT * FROM ATM WHERE TRANSACTION_TIME BETWEEN '2005-02-28 21:00:00' AND '2008-12-25 00:00:00';


3 Answers

If you were using SQL Server 2012, you would use lag or lead for this. Instead, I'm going to use a correlated subquery:

select min(period) as period, MIN(date), MAX(date)
from (select t.*,
             (select min(date) from t t2 where t2.period <> t.period and t2.date > t.date) as nextp
      from t
     ) t
group by nextp

The inner subquery gets the date of the next period. This is the same for consecutive records with the same period record. I can then use this for grouping.

like image 83
Gordon Linoff Avatar answered Oct 13 '22 00:10

Gordon Linoff


Two recursive cte's that finds the start date and end date in a period.

with CStart as
(
  select Date,
         Period
  from DateTable
  where Date = cast(getdate() as date)
  union all
  select D.Date,
         D.Period
  from DateTable as D
    inner join CStart
      on dateadd(day, -1, CStart.Date) = D.Date and
         CStart.Period = D.Period
),
CEnd as
(
  select Date,
         Period
  from DateTable
  where Date = cast(getdate() as date)
  union all
  select D.Date,
         D.Period
  from DateTable as D
    inner join CEnd
      on dateadd(day, 1, CEnd.Date) = D.Date and
         CEnd.Period = D.Period
),
CPeriod as
(
  select Period
  from DateTable
  where Date = cast(getdate() as date)
)
select Period,
       (select min(Date) from CStart) as StartDate,
       (select max(Date) from CEnd) as EndDate 
from CPeriod

Test on SE-Data

like image 24
Mikael Eriksson Avatar answered Oct 13 '22 00:10

Mikael Eriksson


Give this code a try

DECLARE @TODAYSPERIOD AS VARCHAR(2)

SET @TODAYSPERIOD = (SELECT PERIOD FROM MYTABLE
                    WHERE DATE = (DATEADD(D, DATEDIFF(D, 0, GETDATE()), 0)))

SELECT MAX(DATE), MIN(DATE), @TODAYSPERIOD FROM MYTABLE
WHERE PERIOD = @TODAYSPERIOD AND DATE BETWEEN ((DATEADD(D, DATEDIFF(D, 0, GETDATE()), 0)) - 45) AND ((DATEADD(D, DATEDIFF(D, 0, GETDATE()), 0)) + 45)

Essentially, we're using your table (in the above code, it is referenced to as 'MYTABLE') to find the period and then taking only dates within a 45 day radius (both before and after the current date) that is listed as the same period as today.

Hope this helps!

like image 37
Lloyd Banks Avatar answered Oct 12 '22 23:10

Lloyd Banks