Помещение материала в диапазоны дат в SQL Server 2005 - PullRequest
3 голосов
/ 15 февраля 2011

У меня есть таблица с диапазонами недель (номер недели, дата начала, дата окончания) и таблица с датами обучения (для написания репетиторов (ID преподавателя, tutorial_date, тип учебника (A или B)).

Я хочу создать два запроса, которые показывают диапазоны недель (неделя 1, неделя 2) в верхней части с именами преподавателей сбоку с количеством учебных пособий (типа «А») в диапазоне дат этой недели в каждом блоке. за эту неделю.

Результат должен выглядеть следующим образом:

Количество учебных пособий типа "А"

Tutor|Week One|Week Two|Week Three|Week Four|Total
Joe  |   3    |   5    |    7     |    8    | 23        
Sam  |   2    |   4    |    3     |    8    | 17        

Это означает, что Джо завершил 3 урока на первой неделе, пять на второй неделе, 7 на третьей неделе и 8 на неделе 4.

Во втором запросе должны быть показаны итоги для типа учебника "A" и типа "B"

Tutor|Week One|Week Two|Week Three|Week Four|Total   |
Joe  |  3/1   |   5/3  |   7/2    |   8/2   | 23/8   |     
Sam  |  2/3   |   4/4  |   3/2    |   8/3   | 17/12  |      

Здесь, на первой неделе, Джо провел 3 урока типа A и 1 типа B.

Пример таблицы данных для учебных пособий (первая неделя)

Tutor | Tutorial_ID | Tutorial Date |Type|
------------------------------------------
Joe   |    1        | 2011-01-01    | A  |
Joe   |    2        | 2011-01-02    | A  |
Joe   |    3        | 2011-01-03    | A  |
Joe   |    4        | 2011-01-03    | B  |
Sam   |    5        | 2011-01-01    | A  |
Sam   |    6        | 2011-01-02    | A  |
Sam   |    7        | 2011-01-03    | B  |

Таблица недели выглядит следующим образом:

weekNumber |startDate |endDate
1          |2011-01-01|2011-01-15

Я хотел бы сделать это в SQL Server 2005

1 Ответ

1 голос
/ 26 июля 2012

Есть несколько способов сделать это.

Для запросите один , где вам нужно всего лишь PIVOT для типа 'A', тогда вы можете просто набрать PIVOT

select *
from 
(
  select w1.tutor
    , w1.type
    , wk.weeknumber
  from w1
  inner join wk
    on w1.tutorialdate between wk.startdate and wk.enddate
  where w1.type = 'a'
) x
pivot
(
  count(type)
  for weeknumber in ([1])
)p 

См. SQL Fiddle с демоверсией

Или вы можете использовать Count() с оператором CASE.

select w1.tutor
  , COUNT(CASE WHEN w1.type = 'A' THEN 1 ELSE null END) [Week One]
from w1
inner join wk
  on w1.tutorialdate between wk.startdate and wk.enddate
group by w1.tutor

См. SQL Fiddle с демоверсией

Но для второго запроса я бы просто использовал Count() с CASE

select w1.tutor
  , Cast(COUNT(CASE WHEN w1.type = 'A' AND wk.weeknumber = 1 THEN 1 ELSE null END) as varchar(10))
     + ' / '
     + Cast(COUNT(CASE WHEN w1.type = 'B' AND wk.weeknumber = 1 THEN 1 ELSE null END) as varchar(10)) [Week One]
   , Cast(COUNT(CASE WHEN w1.type = 'A' AND wk.weeknumber = 2 THEN 1 ELSE null END) as varchar(10))
     + ' / '
     + Cast(COUNT(CASE WHEN w1.type = 'B' AND wk.weeknumber = 2 THEN 1 ELSE null END) as varchar(10)) [Week Two]
from w1
inner join wk
  on w1.tutorialdate between wk.startdate and wk.enddate
group by w1.tutor

См. SQL Fiddle с демонстрацией

Редактировать, как AndriyM указал, что второе можно сделать с помощью PIVOT. Вот решение для второго запроса:

SELECT *
FROM
(
  select distinct w1.tutor
    , wk.weeknumber
    , left(total, len(total)-1) Totals
  FROM w1
  inner join wk
      on w1.tutorialdate between wk.startdate and wk.enddate
  CROSS APPLY
  (
    SELECT cast(count(w2.type) as varchar(max)) + ' / '
    from w1 w2
    inner join wk wk2
      on w2.tutorialdate between wk2.startdate and wk2.enddate
    WHERE w2.tutor = w1.tutor
      AND wk2.weeknumber = wk.weeknumber
    group by w2.tutor, wk2.weeknumber, w2.type
    FOR XML PATH('')
  )  D ( total )
)  x
PIVOT
(
  min(totals)
  for weeknumber in ([1], [2])
) p

См. SQL Fiddle с демоверсией

...