Диапазон дат GROUP BY? - PullRequest
0 голосов
/ 12 марта 2012

У меня есть следующая хранимая процедура:

SELECT tsks.grouping_ref, ttg.description AS grouping_desc, 
SUM(ts.booked_time) AS booked_time_total, 
DATENAME(MONTH, ts.start_dtm) + ' ' + DATENAME(YEAR, ts.start_dtm) AS month_name,
@month_ref AS month_ref

FROM timesheets ts
JOIN timesheet_categories cat
ON ts.timesheet_cat_ref = cat.timesheet_cat_ref

JOIN timesheet_tasks tsks
ON ts.task_ref = tsks.task_ref

JOIN timesheet_task_groupings ttg
ON tsks.grouping_ref = ttg.grouping_ref

WHERE ts.status IN(1, 2) --Booked and approved
AND cat.is_leave_category = 0 --Ignore leave
--AND DATEPART(YEAR, ts.start_dtm) = @Year
--AND DATEPART(MONTH, ts.start_dtm) = @Month

--accounting months 2012
AND (@month_ref = 81201 AND ts.start_dtm Between '2011-11-28' AND '2012-01-01')
  or (@month_ref = 81202 AND ts.start_dtm Between '2012-01-02' AND '2012-01-29')
  or (@month_ref = 81203 AND ts.start_dtm Between '2012-01-30' AND '2012-02-26')
  or (@month_ref = 81204 AND ts.start_dtm Between '2012-02-27' AND '2012-04-01')
  or (@month_ref = 81205 AND ts.start_dtm Between '2012-04-02' AND '2012-04-29')
  or (@month_ref = 81206 AND ts.start_dtm Between '2012-04-30' AND '2012-05-27')
  or (@month_ref = 81207 AND ts.start_dtm Between '2012-05-28' AND '2012-06-01')
  or (@month_ref = 81208 AND ts.start_dtm Between '2012-07-02' AND '2012-07-29')
  or (@month_ref = 81209 AND ts.start_dtm Between '2012-07-30' AND '2012-08-26')
  or (@month_ref = 81210 AND ts.start_dtm Between '2012-08-27' AND '2012-09-30')
  or (@month_ref = 81211 AND ts.start_dtm Between '2012-10-01' AND '2012-10-28')
  or (@month_ref = 81212 AND ts.start_dtm Between '2012-10-29' AND '2012-11-25')


GROUP BY tsks.grouping_ref, ttg.description,
DATENAME(MONTH, ts.start_dtm),
DATENAME(YEAR, ts.start_dtm)
ORDER BY grouping_desc

По существу, это фильтрация результатов на основе диапазонов дат, а затем группировка результатов следующим образом:

Job Group | Month  | Booked Hours

   Test   | Feb 12 |    7

Затем пользователь нажимает на кнопку «Тест», где он увидит отчет за 7 забронированных часов. Я хотел бы группировать по диапазонам дат?

Я знаю, что это создает месяц:

DATENAME(MONTH, ts.start_dtm),
DATENAME(YEAR, ts.start_dtm)

Но диапазоны по дате должны отображаться только при наличии результатов, т. Е. Тест может быть в диапазоне 1, поэтому он будет отображаться, иначе диапазоны дат не будут отображаться.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 13 марта 2012

Мне все еще не ясно на 100%, что вы ищете.Я сделаю это как можно лучше.

Я использую таблицу дат, используя month_ref и month_name, которые использует ваша компания.Как вы видите, после того, как вы заполнили таблицу дат, она содержит все данные, относящиеся к дате, которая вам когда-либо понадобится.Используйте month_name как в элементах SELECT, так и в частях GROUP.

Обратите внимание, насколько проще становится запрос после использования таблицы дат.

CREATE TABLE Dates(
  TheDate       DATE    NOT NULL,
  month_ref     INT     NOT NULL,
  month_name    VARCHAR(10)
) 

INSERT INTO Dates(TheDate, month_ref, month_name) VALUES
('20120312', 81204, 'March 2012')

DECLARE @month_ref INT
SET @month_ref = 81204

SELECT tsks.grouping_ref, 
  ttg.description AS grouping_desc, 
  SUM(ts.booked_time) AS booked_time_total, 
  Dates.MyDisplayValue AS month_name,
  Dates.month_ref AS month_ref
FROM timesheets ts
  JOIN timesheet_categories cat
    ON ts.timesheet_cat_ref = cat.timesheet_cat_ref
  JOIN timesheet_tasks tsks
    ON ts.task_ref = tsks.task_ref
  JOIN timesheet_task_groupings ttg
    ON tsks.grouping_ref = ttg.grouping_ref
  INNER JOIN Dates 
    ON ts.start_dtm = Dates.TheDate
WHERE ts.status IN(1, 2) --Booked and approved
  AND cat.is_leave_category = 0 --Ignore leave
  AND Dates.month_ref = @month_ref
GROUP BY tsks.grouping_ref, 
  ttg.description,
  Dates.MyDisplayValue,
  Dates.month_ref
ORDER BY grouping_desc
2 голосов
/ 12 марта 2012

Я не понимаю вашего вопроса.

После просмотра

AND (@month_ref = 81201 AND ts.start_dtm Between '2011-11-28' AND '2012-01-01')
  or (@month_ref = 81202 AND ts.start_dtm Between '2012-01-02' AND '2012-01-29')

Я помню, как выглядел наш код 2 года назад.Вы можете рассмотреть возможность добавления DatesTable в вашу базу данных.У нас мы храним все даты с момента создания нашей компании до настоящего времени и даты на следующие 20 лет.Каждый день имеет ряд атрибутов (измерения, столбцы, как бы вы их ни называли) IsWeekDay, IsHolliday, Quarter, YearNr, MonthNr, WeekNr, DayName, MonthName, ... вы можете добавить любые дополнительные столбцы, которые требуются вашему бизнесу.

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

Мне потребовалось менее полдня, чтобы Google начал некоторые запросы, чтобы заполнить эту таблицу.Сначала мы сделали это для нашего хранилища данных, но теперь его использует каждый отдел, чтобы рассчитать базы для чеков на работе в будние, субботние, воскресные и праздничные дни;финансовые отчеты по неделям, месяцам, годам, кварталам, ...

Это значительно упростило наши запросы.

1 голос
/ 12 марта 2012

Я второе, что сказал Вим, потому что это полное решение. Если вы хотите исправить вашу текущую проблему, вам будет лучше, если вы создадите таблицу диапазонов и их имен, объедините и сгруппируйте по имени диапазона:

select dr.Name ...
 ...
inner join date_ranges dr
  on ts.start_dtm between dr.StartDate and dr.EndDate
  and dr.ID = @month_ref
 ...
group by dr.Name ...

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

РЕДАКТИРОВАТЬ: группировка по диапазону

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

case @month_ref when '81201' then '1 2012' when '81202' then '2 2012' etc end. 

Если вы хотите более универсальное решение, проверьте start_dtm в выражении case, например:

case when start_dtm between ... then '1 2012' .... end. 

Но тогда вам придется повторить это в группе. Первое решение, которое я вам дал, избавило бы вас от необходимости копировать-вставлять и выискивать ошибки.

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