문제

다음과 같은 방식으로 구성된 데이터 세트가 있습니다.

Timestamp|A0001|A0002|A0003|A0004|B0001|B0002|B0003|B0004 ...
---------+-----+-----+-----+-----+-----+-----+-----+-----
2008-1-1 |  1  |  2  | 10  |   6 |  20 |  35 | 300 |  8
2008-1-2 |  5  |  2  |  9  |   3 |  50 |  38 | 290 |  2    
2008-1-4 |  7  |  7  | 11  |   0 |  30 |  87 | 350 |  0
2008-1-5 |  1  |  9  |  1  |   0 |  25 | 100 |  10 |  0
...

여기서 A0001은 항목 #1의 값 A이고 B0001은 항목 #1의 값 B입니다. 테이블에는 60 가지가 넘는 항목이있을 수 있으며 각 항목에는 A 값 열과 B 값 열이있어 테이블에 총 120 개의 열이 있습니다.

내가 가고 싶은 곳은 각 항목의 a와 b 값을 합산하는 3 열 결과 (항목 색인, A 값, B 값)입니다.

Index | A Value | B Value
------+---------+--------
 0001 |   14    |   125
 0002 |   20    |   260
 0003 |   31    |   950
 0004 |    9    |    10
 .... 

열에서 행으로 가면서 솔루션의 피벗을 기대할 수 있지만 어떻게 살리하는지 확실하지 않습니다. 이 문제의 일부는 A와 B를 제거하는 방법으로 인덱스 열의 값을 형성하는 방법입니다. 다른 부분은 전에 피벗을 사용한 적이 없어서 기본 구문을 넘어서고 있다는 것입니다.

나는 궁극적으로 다음과 같은 요약을 구축하는 멀티 스텝 솔루션이 필요하다고 생각합니다.

ColName | Value
--------+------
A0001   |  14
A0002   |  20
A0003   |  31
A0004   |   9
B0001   | 125
B0002   | 260
B0003   | 950
B0004   |  10

그런 다음 colname 데이터를 수정하여 색인을 제거합니다.

ColName | Value | Index | Aspect
--------+-------+-------+-------
A0001   |  14   | 0001  |  A
A0002   |  20   | 0002  |  A
A0003   |  31   | 0003  |  A
A0004   |   9   | 0004  |  A
B0001   | 125   | 0001  |  B
B0002   | 260   | 0002  |  B
B0003   | 950   | 0003  |  B
B0004   |  10   | 0004  |  B

마지막으로 자체 조인하여 B 값을 A 값 옆에 이동합니다.

이것은 내가 원하는 것을 얻기위한 긴 바람 과정 인 것 같습니다. 그래서 나는 올바른 길로 향하는지에 대한 조언을 받거나, 내 인생을 훨씬 쉽게 만들 수있는 또 다른 접근법이 있습니까?

주 1) 솔루션은 MSSQL 2005에서 T-SQL에 있어야합니다.

참고 2) 테이블 형식을 변경할 수 없습니다.

편집하다 각 열에서 노조와 개별 합계를 사용하는 것에 대해 생각한 또 다른 방법 :

SELECT '0001' as Index, SUM(A0001) as A, SUM(B0001) as B FROM TABLE
UNION
SELECT '0002' as Index, SUM(A0002) as A, SUM(B0002) as B FROM TABLE
UNION
SELECT '0003' as Index, SUM(A0003) as A, SUM(B0003) as B FROM TABLE
UNION
SELECT '0004' as Index, SUM(A0004) as A, SUM(B0004) as B FROM TABLE
UNION
...

그러나이 접근법은 실제로 그리 좋지 않습니다

편집하다 지금까지 두 가지 큰 응답이 있습니다. 하지만 쿼리에 두 가지 조건을 추가하고 싶습니다 :-)

1) 타임 스탬프 범위 (Minv <timestamp <maxv)를 기준으로 행을 선택해야합니다.

2) 타임 스탬프를 처리하는 UDF에서 조건부로 행을 선택해야합니다.

Brettski의 테이블 이름을 사용하면 위의 것이 다음으로 번역됩니다.

...
(SELECT A0001, A0002, A0003, B0001, B0002, B0003 
 FROM ptest 
 WHERE timestamp>minv AND timestamp<maxv AND fn(timestamp)=fnv) p
unpivot
(val for item in (A0001, A0002, A0003, B0001, B0002, B0003)) as unpvt
...

조건부 FN () 요구 사항을 추가한다는 점을 감안할 때 Jonathon이 제안한대로 동적 SQL 경로를 내려야한다고 생각합니다. 특히 12 개의 다른 테이블에 대해 동일한 쿼리를 만들어야합니다.

도움이 되었습니까?

해결책

여기에도 같은 대답이 재미있었습니다.

-- Get column names from system table
DECLARE @phCols NVARCHAR(2000)
SELECT @phCols = COALESCE(@phCols + ',[' + name + ']', '[' + name + ']') 
    FROM syscolumns WHERE id = (select id from sysobjects where name = 'Test' and type='U')

-- Get rid of the column we don't want
SELECT @phCols = REPLACE(@phCols, '[Timestamp],', '')

-- Query & sum using the dynamic column names
DECLARE @exec nvarchar(2000)
SELECT @exec =
'
    select
        SUBSTRING([Value], 2, LEN([Value]) - 1) as [Index],
        SUM(CASE WHEN (LEFT([Value], 1) = ''A'') THEN Cols ELSE 0 END) as AValue, 
        SUM(CASE WHEN (LEFT([Value], 1) = ''B'') THEN Cols ELSE 0 END) as BValue
    FROM
    (
        select *
        from (select ' + @phCols + ' from Test) as t
        unpivot (Cols FOR [Value] in (' + @phCols + ')) as p
    ) _temp
    GROUP BY SUBSTRING([Value], 2, LEN([Value]) - 1)
'
EXECUTE(@exec)

이 코드 열 이름은 하드 코드 열 이름을 필요로하지 않습니다.

다른 팁

좋아, 나는 당신이 시작해야 할 하나의 솔루션을 생각해 냈습니다. 모일 시간이 조금 걸릴 것이지만 잘 수행 할 것입니다. 모든 열을 이름으로 나열 할 필요가 없다면 좋을 것입니다.

기본적으로 이것은 비 VOT를 사용하여 해당 제품을 임시 테이블에 배치 한 다음 최종 데이터 세트에 쿼리합니다. 나는 이것을 정리할 때 내 테이블 ptest를 명명했습니다. 이것은 모든 A0001 등 열이있는 것입니다.

-- Create the temp table
CREATE TABLE #s (item nvarchar(10), val int)

-- Insert UNPIVOT product into the temp table
INSERT INTO  #s (item, val)
SELECT item, val
FROM
(SELECT A0001, A0002, A0003, B0001, B0002, B0003
FROM ptest) p
unpivot
(val for item in (A0001, A0002, A0003, B0001, B0002, B0003)) as unpvt

-- Query the temp table to get final data set
SELECT RIGHT(item, 4) as item1,
Sum(CASE WHEN LEFT(item, 1) = 'A' THEN val ELSE 0 END) as A,
Sum(CASE WHEN LEFT(item, 1) = 'B' THEN val ELSE 0 END) as B
from #s
GROUP BY RIGHT(item, 4)

-- Delete temp table 
drop table #s

그건 그렇고, 질문에 감사드립니다. 이것은 제가 처음으로 제가 해제를 사용해야했습니다. 항상 원했던 적이 없었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top