SQL Group Distinct Count - PullRequest
       5

SQL Group Distinct Count

2 голосов
/ 10 мая 2011

У меня есть следующая таблица

User ID    Start Date   End Date
-------------------------------------
John Doe   Mar 11 2011  May 28 2011
Robret S   Mar 21 2011  Jun 29 2011
Tina T     Feb 01 2011  August 20 2011

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

Ожидаемый результат:

February  = 1 Resource
March     = 3 Resources
April     = 3 Resources
May       = 3 Resources
June      = 2 Resources
July      = 1 Resource
August    = 1 Resource

Ответы [ 4 ]

2 голосов
/ 10 мая 2011
With Calendar As
    (
    Select Cast('20110501' As DateTime) As [Date]
    Union All
    Select DateAdd(m,-1,[Date])
    From Calendar
    Where [Date] > DateAdd(m,-5,'20110501')
    )
Select DateName(m, C.Date) + ' ' + Cast(Year(C.Date) As char(4))
    , Case Count(*)
        When 1 Then Cast(Count(*) As varchar(10)) + ' Resource'
        Else Cast(Count(*) As varchar(10)) + ' Resources'
        End
From Calendar As C
    Left Join MyTable As T
        On C.Date Between T.StartDate And T.EndDate
Group By C.Date

Результаты:

December 2010   | 1 Resource
January 2011    | 1 Resource
February 2011   | 1 Resource
March 2011      | 1 Resource
April 2011      | 3 Resources
May 2011        | 3 Resources
0 голосов
/ 10 мая 2011
WITH resources AS (
  SELECT
    Date = DATEADD(month, v.number, [Start Date])
  FROM atable t
    INNER JOIN master.dbo.spt_values v ON v.type = 'P'
      AND v.number BETWEEN 0 AND DATEDIFF(month, t.[Start Date], t.[End Date])
)
SELECT
  Month = DATENAME(month, Date),
  ResourceCount = CAST(COUNT(*) AS varchar(30)) +
                  CASE COUNT(*) WHEN 1 THEN ' Resource' ELSE ' Resources' END
FROM resources
WHERE Date > DATEADD(month, -6, DATEADD(day, -DAY(GETDATE()), GETDATE()))
GROUP BY YEAR(Date), MONTH(Date), DATENAME(month, Date)
ORDER BY YEAR(Date), MONTH(Date)
0 голосов
/ 10 мая 2011

Я не думаю, что вы можете делать то, что вы хотите, используя «простое» выражение select (даже используя GROUPing и т. Д.). Это не в моей голове, поэтому вам придется немного поэкспериментировать с и желательно прочитать превосходную книгу SQL для умников Джо Селко .

Вам необходимо создать вторую таблицу, содержащую все ваши месяцы (даты начала / окончания). Вам нужна только одна таблица для всех типов похожих запросов, и она должна содержать все месяцы в диапазонах дат, которые вы интересуетесь запросами:

CREATE TABLE months (id, start DATE, end DATE);

INSERT INTO months (id, start, end) 
          values ( (1, 2011-01-01, 2011-01-31), 
                   (2, 2011-02-01, 2011-02-28), ...);

Затем вы ВНЕШНИЙ ВНЕШНИЙ ВХОД со своей таблицы пользователей на эту таблицу месяцев. Это даст вам строку для каждого пользователя за каждый месяц, в течение которого он был доступен, и вы можете при необходимости ГРУППАТЬ:

SELECT months.id, COUNT(user.id) 
  FROM months LEFT OUTER JOIN users 
         ON user.start_date < months.end 
        AND user.end_date > months.start 
GROUP BY months.id;

Надеюсь, это поможет.

0 голосов
/ 10 мая 2011

Вам понадобятся существующие записи данных за последние 6 месяцев, чтобы вы могли объединить два набора данных. Вы можете создать последние 6 месяцев в CTE и выполнить левое соединение со своими данными. Это позволит вам показать последние 6 месяцев, даже если у вас нет данных.

...