Получите список дат между двумя датами

Вы используете блок try-исключения для обработки чтения пустых записей, но затем продолжаете пытаться обрабатывать их. Этот код обработки также должен находиться внутри блока try:

# Calculate the min and max values in the current interval based on the SECOND value (force, not distance)
# This is what the lambda function is for
try:
    minimum = min(current_interval, key=lambda t: int(t[1]))
    maximum = max(current_interval, key=lambda t: int(t[1]))

    # This was originally outside the "try" block
    # Write the values for the current interval
    datawriter.writerow([interval_count, '', minimum[1], minimum[0], '', maximum[1], maximum[0]])

    interval_count += 1  # Update count

except ValueError:
    pass  # Code was throwing errors for blank entries, this just skips them
87
задан Ferdinand Gaspar 19 September 2017 в 23:17
поделиться

7 ответов

Я использовал бы эту хранимую процедуру для генерации интервалов, в которых Вы нуждаетесь во временную таблицу, названную time_intervals, затем ПРИСОЕДИНЯЕТЕСЬ и агрегировали свою таблицу данных с временным файлом таблица time_intervals .

процедура может генерировать интервалы всех различных типов, которые Вы видите указанный в ней:

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 Server.

65
ответ дан Community 24 November 2019 в 07:50
поделиться

Создайте хранимую процедуру, которая берет два параметра a_begin и a_end. Составьте временную таблицу в нем, назвал t, объявите переменную d, присвойте a_begin d и работайте WHILE цикл INSERT луг d в t и вызов ADDDATE функция для постепенного увеличения значения d. Наконец SELECT * FROM t.

0
ответ дан Eugene Yokota 24 November 2019 в 07:50
поделиться

Обычно можно было бы использовать вспомогательный глагол, числа представляют Вас в виде таблицы, обычно имеют в наличии для просто этой цели с некоторой вариацией на это:

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
ответ дан Cade Roux 24 November 2019 в 07:50
поделиться

Одалживая идею от этот ответ, можно настроить таблицу с 0 до 9 и использование что генерировать список дат.

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';

Это позволит Вам генерировать список до 1 000 дат. Если необходимо пойти более крупные, можно добавить другое перекрестное объединение к внутреннему запросу.

8
ответ дан Community 24 November 2019 в 07:50
поделиться

Можно использовать пользовательские переменные 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, потому что Вы добавляете к нему в первый раз, когда Вы используете его. Кроме того, Вы не можете использовать "НАЛИЧИЕ date_sequence", потому что это делает инкремент пользовательской переменной дважды для каждой строки.

12
ответ дан Andrew Vit 24 November 2019 в 07:50
поделиться

У нас была подобная проблема с отчетами BIRT, в которых мы хотели сообщить в те дни, которые не имели никаких данных. С тех пор не было никаких записей для тех дат, самое легкое решение для нас состояло в том, чтобы составить простую таблицу, которая сохранила все даты, и используйте это, чтобы заставить диапазоны или соединение получать нулевые значения для той даты.

у Нас есть задание, которое работает каждый месяц, чтобы гарантировать, что таблица заполняется 5 лет в будущее. Таблица составлена таким образом:

create table all_dates (
    dt date primary key
);

Несомненно существуют волшебные хитрые способы сделать это с другим DBMS, но мы всегда выбираем простое решение. Требования устройства хранения данных для таблицы минимальны, и она делает запросы настолько более простыми и портативными. Этот вид решения почти всегда лучше с точки зрения производительности, так как это не требует вычислений на строку на данных.

другая опция (и мы использовали это прежде) состоит в том, чтобы гарантировать, что существует запись в таблице для каждой даты. Мы периодически развертывали таблицу и добавляли нулевые записи для дат и/или времена, которые не существовали. Это не может быть опцией в Вашем случае, это зависит от хранивших данных.

, Если Вы действительно думаете, что это - стычка для хранения all_dates таблица заполненным, хранимая процедура является способом пойти, который возвратит набор данных, содержащий те даты. Это почти наверняка будет медленнее, так как необходимо вычислить диапазон каждый раз, когда вместо этого называют того, чтобы просто вытянуть предварительные расчетные данные от таблицы.

, Но, честно говоря, Вы могли заполнить таблицу в течение 1 000 лет без любых серьезных проблем хранения данных - 365 000 16 байтов (например), даты плюс индекс, копирующий дату плюс 20% наверху для безопасности, я примерно оценю приблизительно в 14M [365,000 * 16 * 2 * 1.2 = 14 016 000 байтов]), крохотная таблица в схеме вещей.

13
ответ дан paxdiablo 24 November 2019 в 07:50
поделиться

Я бы использовал что-то подобное:

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 хранятся все даты, увеличенные на день между этими двумя датами, которые можно соединять по своему усмотрению.

0
ответ дан 24 November 2019 в 07:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: