Как подсчитать несколько разных полей без повторения запроса?

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

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 проблемы с этим:

Вы не можете перечислить 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
 user35904012 мар. 2012 г., 11:52
Если вы группируете поsomeID а такжеsomeDate в вашем запросе количество различных комбинацийsomeID а такжеsomeDate всегда будет 1 в каждом ряду. Должны ли мы предполагать, что вы хотите вернуть количество различных комбинаций полей, которыене быть сгруппированными в основном запросе, или вы хотите посчитать комбинации по нескольким различным строкам, возвращаемым вашим запросом? Вы также можете подтвердить, используете ли вы SQLServer 2000 или более новую версию?

Ответы на вопрос(2)

Вы можете попробовать с подсчетомнад разделом«:

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 ...

ОБНОВЛЕНО

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

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)

 froadie12 мар. 2012 г., 11:33
сделанный. Извините за путаницу
 Damien_The_Unbeliever12 мар. 2012 г., 11:19
@froadie - да, желательно с некоторыми примерами данных, чтобы мы могли лучше понять, к чему вы стремитесь. (Пример данных в таблице и ожидаемых результатов запроса будет хорошим)
 froadie12 мар. 2012 г., 15:46
Каковы преимущества вашего запроса над моим?
 froadie12 мар. 2012 г., 11:13
Вы правы, я пропустил некоторую применимую информацию - я не хочу, чтобы количество различных идентификаторов в день, я хочу, чтобы количество в месяц, но разные идентификаторы в день. Обновление вопроса, так что, если это не имеет смысла, проверьте там
 Damien_The_Unbeliever12 мар. 2012 г., 11:48
@froadie - новый запрос в верхней части ответа дает требуемый результат.

Ваш ответ на вопрос