Как подсчитать несколько разных полей без повторения запроса? - PullRequest
0 голосов
/ 12 марта 2012

У меня есть запрос с несколькими группировками, который возвращает количество в месяц.Примерно так:

SELECT field1, field2, year(someDate), month(someDate), count(*) as myCount
FROM myTable
WHERE field5 = 'test'
GROUP BY field1, field2, year(someDate), month(someDate)

Проблема в том, что я хочу, чтобы количество было разным в день, основываясь на поле идентификатора + поле даты (без времени).Например, я хочу получать различное количество идентификаторов каждый день в месяц.Поэтому я хочу что-то вроде этого:

SELECT field1, field2, year(someDate), month(someDate), 
       count(distinct someID, someDate) as myCount
FROM myTable
WHERE field5 = 'test'
GROUP BY field1, field2, year(someDate), month(someDate)

Есть 2 проблемы с этим:

  1. Вы не можете перечислить 2 отдельных поля для совокупности подсчета
  2. Это будет также включать время даты, так что оно не будет ничего фильтровать, поскольку почти всегда будет иметь другое время

Я легко могу позаботиться о 2., преобразовав в varcharтолько даты, но я не уверен, как бороться с проблемой нескольких различных полей.Я не могу использовать это решение , так как я не хочу повторять весь оператор where и group by.Вот что я придумал:

SELECT field1, field2, year(someDate), month(someDate), 
       count(distinct someID + CONVERT(VARCHAR, someDate, 112)) as myCount
FROM myTable
WHERE field5 = 'test'
GROUP BY field1, field2, year(someDate), month(someDate)

Вместо того, чтобы перечислять отдельные поля в списке через запятую, я просто объединял их.Есть ли у этого метода недостатки, на которые мне следует обратить внимание?Могу ли я рассчитывать на это, чтобы быть точным?И - есть ли лучший способ сделать это?

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

Некоторые основные примерные данные и ожидаемый результат (пропуская field1 и field2 для этого):

*Date*              *ID*
1/3/12 00:00:09     22
1/3/12 00:13:00     22
1/4/12 12:00:00     22
1/7/12 15:00:45     27
1/15/12 15:00:00    22
2/6/12 00:00:09     50
2/8/12 00:13:00     44
2/8/12 12:00:00     45
2/22/12 15:00:45    33
2/22/12 15:00:00    33
2/22/12 15:00:00    44

*Year*  *Month* *Count*
2012    Jan     4
2012    Feb     5

Ответы [ 2 ]

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

ОБНОВЛЕНО

Исходя из ваших данных выборки, это дает требуемый результат:

Declare @Tab table ([Date] datetime,ID int)
insert into @Tab([Date],ID) values
('2012-01-03T00:00:09.000', 22),
('2012-01-03T00:13:00.000', 22),
('2012-01-04T12:00:00.000', 22),
('2012-01-07T15:00:45.000', 27),
('2012-01-15T15:00:00.000', 22),
('2012-02-06T00:00:09.000', 50),
('2012-02-08T00:13:00.000', 44),
('2012-02-08T12:00:00.000', 45),
('2012-02-22T15:00:45.000', 33),
('2012-02-22T15:00:00.000', 33),
('2012-02-22T15:00:00.000', 44)

select DATEADD(month,DATEDIFF(month,0,[Date]),0) as MonthStart,SUM(distinctDayIDs)
from
(
    SELECT DATEADD(day,DATEDIFF(day,0,[Date]),0) as [Date], 
           count(distinct ID) as distinctDayIDs
    FROM @Tab
    --WHERE field5 = 'test'
    GROUP BY DATEADD(day,DATEDIFF(day,0,[Date]),0)
) t
group by DATEADD(month,DATEDIFF(month,0,[Date]),0)

Я думаю, потому что мы должны делать подсчет на каждый день, мы должны сделать это как две отдельные операции группировки.


Предыдущий ответ

Похоже, что желаемый результат будет field1, field2, дата и количество различных идентификаторов на эту дату?

Если так, я думаю, вы слишком усложняете вещи:

SELECT field1, field2, DATEADD(day,DATEDIFF(day,0,someDate),0) as Date, 
       count(distinct someID) as myCount
FROM myTable
WHERE field5 = 'test'
GROUP BY ffield1, field2, DATEADD(day,DATEDIFF(day,0,someDate),0)

(я использую DATEADD / DATEDIFF чтобы вырезать часть времени вместо преобразования в varchar)

0 голосов
/ 12 марта 2012

Вы можете попробовать с количеством ' по разделу ':

SELECT 
   field1, field2, someID, someDate, 
   count(*) OVER(PARTITION BY someID, someDate) as myCount
FROM myTable
WHERE field5 = 'test'
GROUP BY field1, field2, someID, someDate

или подготовить CTE:

;with cte as (
   select someDate, count( someID) as myCount
   from myTable
   group by someDate)
 select m.field1, m.field2, m.someID, m.someDate, cte.myCount
 from myTable m inner join cte 
   on m.someDate = cte.someDate
 where ...
...