Проверить наличие строк за последние n дней - PullRequest
1 голос
/ 29 сентября 2011

Я хочу выполнить проверку "есть ли запись для каждого из последних 100 дней в таблице", где в таблице есть что-то вроде столбца контрольной даты, и он думал о присоединении к подзапросу, который возвращает sysdate - 0, sysdate - 1, ... sysdate - 100.

Обновления (для уточнения):

  • Мне нужно знать, какие даты отсутствуют за последние n дней
  • Я хочу избежать дополнительных таблиц (также временных таблиц)

Это хороший подход?

Ответы [ 5 ]

4 голосов
/ 30 сентября 2011

Предполагая, что ваша таблица Oracle выглядит следующим образом ...

CREATE TABLE DATE_TABLE (
    D DATE,
    -- And other fields, PK etc...
)

... и предполагая, что D содержит "круглые" даты (т.е. без времени суток), следующий запрос даст вам все пропущенные даты между :min_date и :min_date + :day_count:

SELECT *
FROM (
    SELECT (TO_DATE(:min_date) + LEVEL - 1) GENERATED_DATE
    FROM DUAL
    CONNECT BY LEVEL <= :day_count
)
WHERE
    GENERATED_DATE NOT IN (SELECT D FROM DATE_TABLE)

Простым английским языком:

  1. Генерация всех дат в заданном интервале (подзапрос).
  2. Проверьте, отсутствует ли какой-либо из них в таблице (супер-запрос).
3 голосов
/ 29 сентября 2011

Это то, что вы ищете:

Select seqnum.date, count(issues.id)
from
(
SELECT
    Curdate() - interval (TENS.SeqValue + ONES.SeqValue) day Date
FROM
    (
    SELECT 0 SeqValue 
    UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 
    UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 
    ) ONES
CROSS JOIN
    (
    SELECT 0 SeqValue 
    UNION SELECT 10 UNION SELECT 20 UNION SELECT 30 UNION SELECT 40 UNION SELECT 50 
    UNION SELECT 60 UNION SELECT 70 UNION SELECT 80 UNION SELECT 90 
    ) TENS
) seqnum
left join issues on (cast(issues.created_on as date) = seqnum.date)
group by seqnum.date

Я запустил его на экземпляре Redmine, чтобы увидеть, сколько проблем было создано за последние 100 дней, изо дня в день, включая дни, когда не было создано ни одной проблемы. Подстраивайтесь под ваши структуры данных соответственно. Наслаждайтесь:)

2 голосов
/ 29 сентября 2011

Это может помочь вам:

create table your_table (a_date date not null);

insert into your_table values (date(now()-interval 0 day));
insert into your_table values (date(now()-interval 1 day));
insert into your_table values (date(now()-interval 2 day));
insert into your_table values (date(now()-interval 3 day));
insert into your_table values (date(now()-interval 5 day));
insert into your_table values (date(now()-interval 6 day));
insert into your_table values (date(now()-interval 9 day));
insert into your_table values (date(now()-interval 10 day));
insert into your_table values (date(now()-interval 50 day));
insert into your_table values (date(now()-interval 60 day));
insert into your_table values (date(now()-interval 70 day));
insert into your_table values (date(now()-interval 80 day));
insert into your_table values (date(now()-interval 90 day));

select a_date,ifnull(datediff(next_date ,a_date)-1,0) as number_of_days_missing_after_date
from
(
select dt.a_date,
(select min(a_date) from your_table dtp where dtp.a_date > dt.a_date and dtp.a_date >= date(now()-interval 100 day))  as next_date
from
(select a_date
from your_table
union select date(now()-interval 100 day)) dt
where dt.a_date >= date(now()-interval 100 day)
) a;

Должен дать вам указание относительно того, какие даты отсутствуют.

Я создал таблицу your_table вместо таблицы, которую вы планируете проверить на наличие пропущенных дат (чтобы я мог более наглядно проиллюстрировать вам ваш пример).

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

Надеюсь, это поможет и удачи!

1 голос
/ 29 сентября 2011

В MySQL:

SELECT * FROM `table_name` WHERE `date_column` > DATE_SUB(CURDATE(), INTERVAL 99 DAY)

См. Арифметика даты MySQL

1 голос
/ 29 сентября 2011

Если пробелов нет (например, в выходные дни), вы можете использовать трюк

SELECT COUNT(DISTINCT somedate)=100 FROM sometable  -- evaluates to boolean
WHERE somedate>=sysdate-100;

В зависимости от вашей СУБД, GROUP BY может работать быстрее, чем COUNT DISTINCT.

[Опубликовать уточняющий комментарий]

Как вы уже объяснили, я думаю, вы хотите LEFT JOIN между плотным списком дат и вашей таблицей, затем COUNT и GROUP BY.Если вы используете MySQL, способ создания списка дат в подзапросе описан в этом раннем stackoverflow (я не знаю MySQL достаточно хорошо, чтобы думать о принятом ответе).В большинстве других систем БД это проще.

Решение, упомянутое в этой ссылке постоянной таблицы календаря, тоже не так уж плохо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...