2016-03-28 1 views
0

Итак, я подсчитываю записи активности от пользователей в моей системе. Я получаю счетчик активности на каждый день в определенный месяц и год, так же, как запрос, который следуетПолучите «нуль» для подсчета в датах без записей

SELECT CONVERT(date, VIS_DATETIME) AS DATETIME, COUNT(*) AS ACTIVITY 
FROM ACTIVITY 
WHERE DATEPART(year, VIS_DATETIME) = 2016 AND 
     DATEPART(month, VIS_DATETIME) = 3 
GROUP BY CONVERT(date, VIS_DATETIME) 
ORDER BY CONVERT(date, VIS_DATETIME) 

Вопрос заключается в том, если, скажем, 28 марта не имеет какой-либо деятельности, не будет быть даже перечисленным. Но, для моего API диаграмм, мне нужно получить список и с 0 для счетчика.

Очевидно, что принимали предложения!

+7

Обсуждалось много раз. У вас должна быть таблица календаря. Затем вы берете таблицу календаря и левее присоединяетесь к ACTIVITY, группируя по идентификатору таблицы календаря. –

+0

Ищет нечто более инновационное, но спасибо! –

+1

Календарный стол или таблица подсчета - лучший способ справиться с этим. Не уверен, что еще вы будете делать. Должна быть строка для сервера sql для ее возврата. –

ответ

3

Создать таблицу, содержащую все даты. Затем сделайте левое соединение с таблицей Activity. Группа на дату и сделайте COUNT на Activity.id. Левое соединение гарантирует, что все даты из таблицы даты включены в набор результатов, даже если они не совпадают в предложении соединения.

+0

Не сказать, что это неправильно, но создание бессмысленных структур - плохая практика. Работает для приложения, но разрушает схему БД. Как я уже сказал в комментарии выше, я искал более инновационное решение, которое я мог бы сделать только с запросом. –

+2

Это не бессмысленная структура. Это отличное место для использования таблицы таллинга. –

+1

Все таблицы дат очень полезны и не являются бессмысленной структурой вообще. Зачем создавать более инновационные решения, если это хорошее и проверенное решение? :) – Arvo

3
Declare @DayOfMonth TinyInt Set @DayOfMonth = 1 
Declare @Month TinyInt Set @Month = 1 
Declare @Year Integer Set @Year = 2016 
Declare @startDate datetime 
Declare @endDate datetime 
-- ------------------------------------ 
Select @startDate = DateAdd(day, @DayOfMonth - 1, 
      DateAdd(month, @Month - 1, 
       DateAdd(Year, @Year-1900, 0))) 

select @endDate = dateadd(month,1,@startDate) 

;with dateRange as 
(
    select dt = dateadd(dd, 0, @startDate) 
    where dateadd(dd, 0, @startDate) < @endDate 
    union all 
    select dateadd(dd, 1, dt) 
    from dateRange 
    where dateadd(dd, 1, dt) < @endDate 
) 
select * 
from dateRange 

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

0

Хммм, если вы хотите инновационный. Вот два шага:

  • Добавить флаг в таблицу о действительно ли
  • Добавить задание агента SQL Server активность

Как сделать эти работы?

alter table activity add column ActivityIsValid smallint default 1; 

Таким образом, новые строки действуют как действительные действия, а не недействительны.

Затем запланировать задание агента SQL Server, чтобы запустить следующий код один раз в день:

insert into activity(vis_datetime, ActivityIsValid) 
    values(cast(getdate() as date), 0); 

Затем вы можете запустить свой запрос как:

SELECT CONVERT(date, VIS_DATETIME) AS DATETIME, 
     SUM(CASE WHEN ActivityIsValid = 1 THEN 1 ELSE 0 END) AS ACTIVITY 
FROM ACTIVITY 
WHERE VIS_DATETIME >= '2016-03-01' AND 
     VIS_DATETIME < '2016-04-01   
GROUP BY CONVERT(date, VIS_DATETIME) 
ORDER BY CONVERT(date, VIS_DATETIME); 

Конечно, это работает только двигаться вперед , Вы можете вручную вставить дополнительные строки в исторические данные.

Также обратите внимание на изменение положения WHERE. Выполняя прямые сравнения дат, механизм SQL может использовать индекс.

+0

Инновации теперь анонимно опущены на Stack Overflow? –

+0

Можете ли вы объяснить аргумент case внутри суммы i.e, SUM (CASE WHEN ActivityIsValid = 1 THEN 1 ELSE 0 END). Каков результат суммы при 1 и 0? – RGS

+1

Что подсчитывает количество строк, где 'ActivityIsValid' принимает значение' 1'. –

Смежные вопросы