Как выбрать минимальные / максимальные даты из таблицы 2 на основе даты в таблице 1 (не получая слишком много данных из сумм) - PullRequest
0 голосов
/ 09 ноября 2009

В связи с вопросом, который я задал ранее здесь , я обнаружил проблему, которая ускользает от меня (очевидно).

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

Итак, если последняя неделя января и первая неделя февраля отсутствовали в ежедневном столе (а у нас были все даты на январь и февраль, но не более), мне нужно было:

MonthStart  DayFirst    DayLast
----------  ----------  ----------
2009-01-01  2009-01-01  2009-01-24
2009-02-01  2009-02-08  2009-02-28

Ответ был:

select
    m.date as m1,
    min(d.date) as m2,
    max(d.date) as m3
from monthly m
join daily d
    on month(d.date) = month(m.date)
    and year(d.date) = year(m.date)
group by m.date
order by m.date

, который работал на спецификации, которые я дал.

К сожалению, реальность кусается, и в ежемесячной таблице (и ежедневной таблице) есть несколько записей с одной и той же датой. В частности:

  • даты: 2007-10-16 до 2007-10-30 (15 дней), 2007-11-01 до 2007-11-30 (30 дней) и 2007-12-01 до 2007-12-15 (15 дней).
  • каждая дата имеет шесть строк в обеих таблицах (поскольку каждая из них имеет строку для трех системных имен и двух периодов.

Проблема в том, что я sum() поле в месячной таблице, и новый запрос получает значения, которые слишком велики (по сравнению с предыдущим запросом, в котором не было объединения).

Агрегация изменяет запрос на:

select
    m.date as m1,
    sum(m.other_field),  -- added this
    min(d.date) as m2,
    max(d.date) as m3
from monthly m
join daily d
    on month(d.date) = month(m.date)
    and year(d.date) = year(m.date)
group by m.date
order by m.date

Я думаю, что значения слишком высоки из-за перекрестного соединения, так как цифры для каждого месяца отсутствуют по постоянному коэффициенту, в зависимости от количества дней в ежедневной таблице за этот месяц.

У меня такой вопрос: как мне агрегировать поле в месячной таблице, не вводя этот фактор в игру и по-прежнему получать минимальные / максимальные даты из ежедневной таблицы за этот месяц?

Ответы [ 2 ]

1 голос
/ 09 ноября 2009

Если таблица monthly содержит одну запись для каждого месяца, вы можете сделать это просто:

select
    m.date as m1,
    m.other_field,
    min(d.date) as m2,
    max(d.date) as m3
from monthly m
join daily d
    on month(d.date) = month(m.date)
    and year(d.date) = year(m.date)
group by m.date, m.other_field
order by m.date

в противном случае:

select m1, sum(other_field), m2, m3
from (
        select
        m.date as m1,
        m.other_field,
        min(d.date) as m2,
        max(d.date) as m3
    from monthly m
    join daily d
        on month(d.date) = month(m.date)
        and year(d.date) = year(m.date)
    group by m.date, m.other_field) A
group by A.m1, A.m2, A.m3
order by A.m1

Обновление от pax: Как ни старайся, я не смог заставить работать решения join должным образом - казалось, все они возвращали те же неверные данные, что и оригинал. В итоге я выбрал решение, отличное от join, поскольку оно работало, а производительность не была большой проблемой, поскольку в таблицах обычно есть 24 строки (для ежемесячных) и 700 строк (для ежедневных). Я редактирую этот ответ и принимаю его, поскольку (1) он действительно помог мне найти правильное решение; и (2) я не хочу писать свой собственный ответ и требовать славы для себя.

Спасибо за вашу помощь. Вот что сработало для меня:

select
    m.date as p1,
    m.grouping_field as p2,
    sum(m.aggregating_field) as p3,
    (select min(date) from daily
        where month(date) = month(m.date)
        and year(date) = year(m.date)) as p4,
    (select max(date) from daily
        where month(date) = month(m.date)
        and year(date) = year(m.date)) as p5
from
    monthly m
group by
    m.date, m.grouping_field

, который дал мне то, что я хотел:

    P1       P2    P3       P4         P5
----------  ----  ----  ----------  ----------
2007-10-01  BoxA  12.3  2007-10-16  2007-10-30
2007-10-01  BoxB  13.6  2007-10-16  2007-10-30
2007-10-01  BoxC   7.4  2007-10-16  2007-10-30
2007-11-01  BoxA  20.3  2007-11-01  2007-11-30
2007-11-01  BoxB  24.2  2007-11-01  2007-11-30
2007-11-01  BoxC  21.7  2007-11-01  2007-11-30
2007-12-01  BoxA   6.9  2007-12-01  2007-12-15
2007-12-01  BoxB   6.4  2007-12-01  2007-12-15
2007-12-01  BoxC   6.9  2007-12-01  2007-12-15
1 голос
/ 09 ноября 2009

Вы можете сгруппировать месяцы в подзапросе:

select
    m.mindate as m1,
    m.sum_other_field,
    min(d.date) as m2,
    max(d.date) as m3
from (
    select 
         month(date) as month,
         year(date) as year,
         sum(other_field) sum_other_field,
         min(date) mindate
    from monthly
    group by month(date), year(date)
) m
join daily d
    on month(d.date) = m.month
    and year(d.date) = m.year
group by m.month
order by m.year
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...