Поворот даты в месяце в виде столбцов;возможно без динамического sql? - PullRequest
0 голосов
/ 15 декабря 2011

Итак, у меня есть таблица SQL, которая содержит информацию о часах, как это.Количество минут, в течение которых сотрудник работал на определенную дату.Таблица содержит данные за несколько лет, но по субботам и воскресеньям, а также по другим нерабочим / выходным дням (за редкими исключениями) не хватает.отчет, который суммирует посещаемость за данный месяц.

 EmployeeId  '11/01/2011'  '11/02/2011' ....  (for all dates in a month)
 -----------------------------------------------------------------------
 001         319           340
 002         355           322
 003         352           351

У меня есть решение, которое работает (см. Ниже) ... , но мой подход использует динамический sql для построения сводного оператора из дней в данном месяце.В глубине души я продолжаю думать, что должен быть способ, который не использует динамический SQL - но он не приходит ко мне.Любые предложения ... я застрял с динамическим SQL?

DECLARE @columns VARCHAR(8000)
DECLARE @headers VARCHAR(8000)
DECLARE @lowdate Date 
DECLARE @highdate Date

SELECT @columns = COALESCE(@columns + ',[' + cast(Attended as varchar) + ']',
                     '[' + cast(Attended as varchar)+ ']')
FROM TimeAttended WHERE attended >= @date and attended <= @highdate
GROUP BY Attended

SELECT @headers = COALESCE(@Headers + ',Sum([' + cast(Attended as varchar) + ']) as [' + cast(Attended as varchar) + ']',
                     'Sum([' + cast(Attended as varchar)+ ']) as [' + cast(Attended as varchar) + ']')
FROM TimeAttended WHERE attended >= @date and attended <= @highdate
GROUP BY Attended

DECLARE @query VARCHAR(8000)
SET @query = '
SELECT employeeid, ' + @headers + '
FROM TimeAttended 
PIVOT
 (
 Sum(TotalMinutes)
 FOR [Attended]
 IN (' + @columns + ')
 )
 AS p group by employeeid'

EXECUTE(@query)

Ответы [ 3 ]

1 голос
/ 15 декабря 2011

Помимо динамического SQL,
Если каждый бит выходных данных будет принадлежать только одному месяцу, то вы можете жестко закодировать все дни с 1 по 31:

with data as (
  select *
  from (
    values
     (001,          '20111101',    319),
     (002,          '20111101',    355),
     (003,          '20111101',    352),
     (001,          '20111102',    340),
     (002,          '20111102',    322),
     (003,          '20111102',    351)
  ) foo (EmployeeID, [Date], [Minutes])
),
prepared_data as (
  select EmployeeID, [Minutes], day([date]) as [day]
  from data
)
select *
from
  prepared_data
  pivot (min([Minutes]) for [day] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31])) pvt
;

И затем позжеэтап скрывать или игнорировать другим способом столбцы, которые имеют только null s.

1 голос
/ 15 декабря 2011

Помимо очевидного использования динамического SQL (которого я обычно предпочитаю избегать, если это возможно), есть два статических варианта.

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

Второй требует думать о данных немного по-другому.
Вместо того чтобы создавать оператор для просмотра определенного набора дат, закодируйте его для просмотра набора за последние 31 день (с некоторой заданной даты).
То есть столбец 2 - это заданная дата, столбец 3 - это заданная дата - 1 день и т. Д .:

SELECT a.Id, COALESCE(b.Minutes, 0), COALESCE(c.Minutes, 0), (etc)
FROM Employees as a
LEFT JOIN TimeClock as b
ON b.EmployeeId = a.id
AND b.Date = @Given
LEFT JOIN TimeClock as c
ON C.EmployeeId = a.Id
AND c.Date = DATEADD(DAY, 1, @Given)
(etc)

... А затем сопоставить его со столбцом 1 результатов и столбцом1 таблицы отображения и т. Д.

0 голосов
/ 15 декабря 2011

Если вы не знаете значения заранее, вам придется использовать динамический SQL, если вы хотите, чтобы заголовки столбцов основывались на значениях.

Единственная база данных, которая может сделать это, - MS Access 'TRANSFORM

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...