SQL ежемесячное объединение и ежемесячный общий процент - PullRequest
3 голосов
/ 16 ноября 2010

Моя голова курит от (глупых) попыток использования JOIN, WITH и GROUP BY, чтобы найти решение для моего довольно распространенного сценария - я просто не могу обернуть голову вокруг него.Позвольте мне сразу привести пример:

У меня есть две таблицы (ColorCount и Colorname):

ColorCount:
ColorID Count Date
1       42    2010-09-07
1       1     2010-09-08
2       22    2010-09-14
1       20    2010-10-10
3       4     2010-10-14

ColorName:
ColorID  Name
1        Purple
2        Green
3        Yellow
4        Red

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

Output:
Month Color   Count Percentage
09    Purple  43    66%
09    Green   22    33%
09    Yellow  0     0%
09    Red     0     0%
10    Purple  20    83%
10    Green   0     0%
10    Yellow  4     16%
10    Red     0     0%

(Обратите внимание, что общее количество месяцев 09 равно 65, следовательно, 66% для Purple, а также 0 's для несуществующих цветов):

Я надеюсь, что кто-то мечтает о SQL, и это простая задача ...

Ответы [ 2 ]

3 голосов
/ 16 ноября 2010

Это работает со следующими предостережениями:

  • Значения даты и времени должны быть только датой
  • В нем перечислены только те месяцы, для которых имеются какие-либо данные
  • Я перечисляю по первому дню месяца, если у вас есть данные, которые пересекают годы (я предполагаю, что вы не хотите объединять данные с января 2009 года с данными с января 2010 года)
  • Точное форматирование столбца в процентахдетали я оставляю до вас, я должен вернуться к работе

код:

;with cte (ColorId, Mth, TotalCount)
 as (select
        ColorId
       ,dateadd(dd, -datepart(dd, Date) + 1, Date) Mth
       ,sum(Count) TotalCount
      from ColorCount
      group by ColorId, dateadd(dd, -datepart(dd, Date) + 1, Date))
 select
    AllMonths.Mth [Month]
   ,cn.Name
   ,isnull(AggData.TotalCount, 0) [Count]
   ,isnull(100 * AggData.TotalCount / sum(AggData.TotalCount * 1.00) over (partition by AllMonths.Mth), 0) Percentage
  from (select distinct Mth from cte) AllMonths
   cross join ColorName cn
   left outer join cte AggData
    on AggData.ColorId = cn.ColorId
     and AggData.Mth = AllMonths.Mth
  order by AllMonths.Mth, cn.ColorId
2 голосов
/ 16 ноября 2010
SELECT
    [Month],
    [Name],
    [Count],
    CASE WHEN TotalMonth=0 THEN 'INF' ELSE cast(round([Count],0)*100.0/TotalMonth,0) as int) + '%' END as [Percentage]
FROM 
(
SELECT 
    [Months].[Month] as [Month],
    CN.[Name],
    isnull(CC.[Count],0) as [Count],
    (SELECT SUM([Count]) FROM ColorCount WHERE 
            datepart(month,[Date])=datepart(month,CC.[Date])
     ) as [TotalMonth]
FROM (SELECT DISTINCT datepart(month,[Date]) as [Month] FROM ColorCount) [Months]
LEFT JOIN ColorName CN ON [Months].[Month]=datepart(month,CC.[Date])
LEFT JOIN ColorCount CC ON CN.ColorID=CC.ColorID
) AS tbl1
ORDER BY
    [Month] ASC,
    [Name] ASC

Что-то в этом роде ... Он не будет отображать ведущий ноль месяца, но имеет ли это значение?

...