COUNT результат SQL-запроса с предложением HAVING - PullRequest
9 голосов
/ 22 сентября 2010

Можете ли вы использовать COUNT в запросе с предложением HAVING, чтобы COUNT возвращал количество строк? Когда я пытаюсь, я получаю счетчик количества раз, когда ID появляется в таблице. Вот запрос:

SELECT col_appid, min(col_payment_issued_date) as PayDate  
FROM tbl_ui_paymentstubs  
WHERE isnull(col_payment_amount,0) > 0  
GROUP BY col_appid  
HAVING min(col_payment_issued_date) >= '09/01/2010' and min(col_payment_issued_date) <= '09/30/2010'

Я вернусь на 6 строк, и это нормально, но я бы хотел вернуть число 6.

Я обнаружил, что могу сделать это таким образом, но мне было интересно, есть ли другой, более элегантный способ:

WITH Claims_CTE(AppID, PayDate) as
(  
 SELECT col_appid, min(col_payment_issued_date) as PayDate
 FROM tbl_ui_paymentstubs
 WHERE isnull(col_payment_amount,0) > 0
 GROUP BY col_appid
 HAVING min(col_payment_issued_date) >= '09/01/2010' and min(col_payment_issued_date) <= '09/30/2010'
)  
 SELECT count(AppID) as Amount from Claims_CTE

`

Ответы [ 3 ]

11 голосов
/ 22 сентября 2010

Использование COUNT с предложением GROUP BY обеспечит счет для каждой группы. Если вы хотите подсчитать количество групп, это должен быть отдельный запрос (как ваш пример CTE).

Я бы просто использовал простой подзапрос вместо CTE:

SELECT COUNT(*) FROM 
 (SELECT col_appid, min(col_payment_issued_date) as PayDate  
  FROM tbl_ui_paymentstubs  
  WHERE isnull(col_payment_amount,0) > 0  
  GROUP BY col_appid  
  HAVING
     min(col_payment_issued_date) >= '09/01/2010'
     and min(col_payment_issued_date) <= '09/30/2010') Claims
4 голосов
/ 22 сентября 2010

Вы также можете использовать подзапрос.

SELECT count(*) as Amount
FROM (
    SELECT col_appid FROM tbl_ui_paymentstubs
    WHERE isnull(col_payment_amount,0) > 0
    GROUP BY col_appid
    HAVING min(col_payment_issued_date) BETWEEN '09/01/2010' AND '09/30/2010'
) Claims
2 голосов
/ 22 сентября 2010

Предполагая, что у вас есть таблица с отдельным списком значений col_appid, которая называется App, этот запрос также работает и может иметь более высокую производительность:

SELECT Count(*)
FROM
   App A
   CROSS APPLY (
      SELECT TOP 1 col_payment_issued_date
      FROM tbl_ui_paymentstubs P
      WHERE
         P.col_payment_amount > 0
         AND A.col_appid = P.col_appid
      ORDER BY col_payment_issued_date
   ) X
WHERE
   X.col_payment_issued_date >= '09/01/2010'
   AND X.col_payment_issued_date < '10/01/2010'

Если нет таблицы приложения, вы можете заменить (SELECT DISTINCT col_appid FROM tbl_ui_paymentstubs) A, но это не будет работать так же хорошо. Он все еще может быть соперником по сравнению с другими данными запросами.

Другие примечания:

  • Вам не нужно делать isnull(column, 0) > 0, потому что column > 0 уже исключает NULL.

  • Запросы @ ar и @bdukes ничего не требуют во внутреннем предложении SELECT, они могут быть просто SELECT 1, что может повысить производительность (больше ничего не меняется)

  • Я надеюсь, что есть ограничение на col_payment_issued_date, чтобы значения не имели временной доли, такой как 11:23 AM, иначе ваше предложение BETWEEN в конечном итоге не будет получать правильные данные за весь месяц.

Обновление

  • Для чего бы то ни было, формат даты '20100901' будет работать везде, с любым языком или настройкой DATEFIRST. Я призываю вас привыкнуть им пользоваться. Другие форматы, такие как '09 / 01/2010 'или' 2010/09/01 'и т. Д., Могут смешивать месяц и день.

@ Д Скотт сказал:

Существует приложение tbl_Application, но в данном случае оно не используется. Я могу присоединиться к нему, но я просто считаю платежи по этому запросу, поэтому он не требуется.

Не могли бы вы попробовать мой запрос и дать мне отзыв о его производительности по сравнению с другими методами? Я надеюсь, что даже с дополнительным соединением в запросе, он работает довольно хорошо.

...