2013-07-24 2 views
0

타임 스탬프를 기반으로 데이터 피벗을 얻으려고합니다. 나는 그들을 30 분짜리 버킷으로 묶고 싶다. 예를 들어, 아래 데이터 :시간별 SQL 피벗 데이터

CREATE TABLE #test (
    Employee nvarchar(20) NOT NULL 
    ,[SaleTime] time NOT NULL 
    ,Amount float NOT NULL 
) 

INSERT INTO #test VALUES 
('A', '08:10', '100.50') 
,('A', '12:20', '758.23') 
,('A', '11:59', '592.11') 
,('B', '12:00', '95.00') 
,('B', '09:01', '29.10') 
,('B', '09:04', '53.22') 
,('C', '11:23', '55.77') 
,('C', '10:40', '128.00') 

나는 결과가

Time   |  A  |  B  |  C  | 
----------------------------------------------------------------- 
08:00 - 08:30 | 100.5  |    |    | 
08:30 - 09:00 |    |    |    | 
09:00 - 09:30 |    |  82.32 |    | 
09:30 - 10:00 |    |    |    | 
10:00 - 10:30 |    |    |    | 
10:30 - 11:00 |    |    |  128.00 | 
11:00 - 11:30 |    |    |  55.77 | 
11:30 - 12:00 | 592.11  |    |    | 
12:00 - 12:30 | 758.23  |  95.00 |    | 
12:30 - 13:00 |    |    |    | 
----------------------------------------------------------------- 

같은 싶습니다 나는이 작업을 수행하기 위해 슬롯에 빈 테이블을 생성해야합니까? CASE WHEN을 사용하지 않고 이것을 수행하는 방법이 있습니까?

감사합니다.

+0

찾기 참조 추가 행의 부부와 함께

먼저 테스트 데이터의 차이를 설명하기 위해 이 링크에서 [1] : http://stackoverflow.com/questions/17668504/how-to-generate-this-sql-query-like-pivot-table#autocomment25736660 – Vijay

답변

2

어쩌면 난 존재하지 않는 문제를 해결하기 위해 시도 직원 수에 따라 동적 인 대체 솔루션을 제안하고 싶습니다 (추가 직원 용 열 추가). 그 슬롯에 하나 이상의 판매가있을 경우 직원 당 시간 슬롯에 판매 된 금액을 합산합니다. 금액을 집계하지 않으면 누군가가 한 번 이상 판매 한 시간대마다 여러 행으로 끝납니다.

시간 슬롯 생성은 Nenads 대답의 우수 솔루션에서 차용 한 것입니다.

DROP TABLE #test; 
CREATE TABLE #test (
    Employee nvarchar(20) NOT NULL 
    ,[SaleTime] time NOT NULL 
    ,Amount float NOT NULL 
) 

INSERT INTO #test VALUES 
('A', '08:10', '100.50') 
,('A', '12:20', '758.23') 
,('A', '11:59', '592.11') 
,('B', '12:00', '95.00') 
,('B', '09:01', '29.10') 
,('B', '09:04', '53.22') 
,('C', '11:23', '55.77') 
,('C', '10:40', '128.00') 
,('D', '09:40', '28.00') 
,('E', '11:40', '50.00') 
,('E', '11:35', '20.00') 

쿼리가 동적 SQL 문을 구축하고 EXECUTE 문을 실행합니다 :

DECLARE @Headers VARCHAR(MAX) 
SELECT @Headers = COALESCE(@Headers + ',[' + Employee + ']', '[' + Employee + ']') 
FROM (SELECT DISTINCT Employee FROM #test) Emp 

DECLARE @SQL NVARCHAR(MAX) 

SET @SQL = N' 

WITH CTE_TimeSlots AS 
(
    SELECT CAST(''8:00'' AS TIME) AS StartTime, CAST(''8:30'' AS TIME) AS EndTime 
    UNION ALL 
    SELECT DATEADD(MI, 30, StartTime), DATEADD(MI, 30, EndTime) 
    FROM CTE_TimeSlots 
    WHERE StartTime <= ''12:00'' 
) 

SELECT * FROM (
    SELECT CONVERT(NVARCHAR(10),StartTime) + '' - '' + CONVERT(NVARCHAR(10),EndTime) AS [Time], Amount, Employee 
    FROM CTE_TimeSlots t 
    LEFT JOIN #test d ON d.SaleTime >= StartTime AND d.SaleTime < EndTime 
    ) innerQuery 
PIVOT (SUM(Amount) FOR Employee IN (' + @Headers + ') 
) AS PivotTable 
'  
--PRINT @SQL -- Uncomment to see the query which will be run 
EXECUTE(@SQL) 
+0

이것은 완벽합니다! 나는 지금까지 mssql에서 CTE 함수에 대해 몰랐다. 커서를 대신 작성하기 직전이었다. 감사합니다 jpw! – d0h

+0

@ d0h 도와 드리겠습니다. [공통 테이블 식] (http://msdn.microsoft.com/en-us/library/ms190766%28v=sql.105%29.aspx)은 정말 강력 할 수 있으므로 더 살펴볼 가치가 있습니다. – jpw

1

재귀 CTE를 사용하여 '실시간으로'시간대를 생성 한 다음 데이터에 연결할 수 있습니다. CASE을 사용하지 않도록하는 방법이 있습니다, 대신 PIVOT 명령을 사용할 수 있습니다,하지만 난이 훨씬 간단하다고 생각 :

WITH CTE_TimeSlots AS 
(
    SELECT CAST('8:00' AS TIME) AS StartTime, CAST('8:30' AS TIME) AS EndTime 
    UNION ALL 
    SELECT DATEADD(MI, 30, StartTime), DATEADD(MI, 30, EndTime) 
    FROM CTE_TimeSlots 
    WHERE StartTime <= '12:00' 
) 
SELECT CONVERT(NVARCHAR(10),StartTime) + ' - ' + CONVERT(NVARCHAR(10),EndTime) AS [Time] 
, CASE WHEN Employee = 'A' THEN Amount END AS A 
, CASE WHEN Employee = 'B' THEN Amount END AS B 
, CASE WHEN Employee = 'C' THEN Amount END AS C 
FROM CTE_TimeSlots t 
LEFT JOIN #test d ON d.SaleTime >= StartTime AND d.SaleTime < EndTime 

SQLFiddle DEMO

+0

감사합니다 Nenad,하지만 위의 jpw의 대답 d CASE가 필요없는 직원을위한 열을 생성합니다! – d0h