2017-02-09 2 views
3

해결 방법 : 간단한 쿼리를 넘어서는 문제없이이 문제를 해결할 수 없었기 때문에 사례 테이블을 내 테이블의 숫자 식별자의 한도까지 하드 코딩해야했습니다.상위 경계를 모르는 경우 PIVOT 대신 집계 사례 문을 사용하는 방법?

기본 키당 하나의 레코드로 여러 필드에서 알 수없는 레코드 수를 나타내는 쿼리를 작성하는 데 도움이 필요합니다.

여기 내 테이블 디자인이다 :

[Column Name] | [Data Type] | [Allow Nulls] 
------------------------------------------- 
*ItemRef  nvarchar(48) Unchecked 
*AttributeID numeric(2, 0) Unchecked 
AttributeName nvarchar(128) Unchecked 
AttributeValue nvarchar(3072) Nullable 
AttributeUOM nvarchar(10) Nullable 

* 편집 : 여기에 몇 가지 샘플 데이터입니다 : 내가 사용하는 생각 처음에는

[ItemRef] | [AttributeName_01] | [AttributeValue_01] | [AttributeName_02] | [AttributeValue_02] | etc... 

: 여기

Product123 | 1 | Brand | MyBrandName 
    Product123 | 2 | Product Line | MyProductLine 
    Product123 | 3 | Color | MyColor 
    Product456 | 1 | Brand | MySecondBrandName 
    Product456 | 2 | Style | MyStyle 

내 원하는 쿼리 결과입니다 PIVOT 쿼리를 사용했지만 여기에 여러 스레드에서 실행되었으므로 Aggregate Case 문을 대신 사용하는 것이 좋습니다. e를 한 눈에 효율적으로 볼 수 있습니다.

그러나 단일 레코드에 몇 가지 속성이 있는지 알 수 없습니다. 그래서 제 질문은 어떻게 속성의 불확실한 양을 더 잘 나타 내기 위해 다음을 쓸 수 있습니까?

SELECT ItemRef 
    , MIN(CASE AttributeID WHEN '1' THEN AttributeName END) AS AttrName01 
    , MIN(CASE AttributeID WHEN '1' THEN AttributeValue END) AS AttrValue01 
    , MIN(CASE AttributeID WHEN '1' THEN AttributeUOM END) AS AttrUom01 
    , MIN(CASE AttributeID WHEN '2' THEN AttributeName END) AS AttrName02 
    , MIN(CASE AttributeID WHEN '2' THEN AttributeValue END) AS AttrValue02 
    , MIN(CASE AttributeID WHEN '2' THEN AttributeUOM END) AS AttrUom02 
    , MIN(CASE AttributeID WHEN '3' THEN AttributeName END) AS AttrName03 
    , MIN(CASE AttributeID WHEN '3' THEN AttributeValue END) AS AttrValue03 
    , MIN(CASE AttributeID WHEN '3' THEN AttributeUOM END) AS AttrUom03 
    , MIN(CASE AttributeID WHEN '4' THEN AttributeName END) AS AttrName04 
    , MIN(CASE AttributeID WHEN '4' THEN AttributeValue END) AS AttrValue04 
    , MIN(CASE AttributeID WHEN '4' THEN AttributeUOM END) AS AttrUom04 
. . . 
    , MIN(CASE AttributeID WHEN '99' THEN AttributeName END) AS AttrName05 
    , MIN(CASE AttributeID WHEN '99' THEN AttributeValue END) AS AttrValue05 
    , MIN(CASE AttributeID WHEN '99' THEN AttributeUOM END) AS AttrUom05 
FROM dbo.ProductAttributes 
GROUP BY ItemRef 
+1

당신이 말하는 것을 동적 교차 탭이라고합니다. 여기 주제에 관한 기사가 있습니다. http://www.sqlservercentral.com/articles/Crosstab/65048/ 몇 가지 샘플 데이터가있는 게시판을 찾는데 문제가 있으면 도와 드리겠습니다. –

+0

좋아요, 당신이 링크 한 기사를 읽었습니다. 이것은 절대적으로 저장 프로 시저를 생성해야합니까? 샘플 데이터는 추측 할 수있는 주요 게시물을 업데이트합니다. – aberrantGeek

+0

확실히 저장 프로 시저가 필요하지 않지만 왜 저장 프로 시저를 만들지 않으십니까? 임시 쿼리에서이를 수행하는 것은 통사론적인 악몽입니다. 그것은 t-SQL에서 충분히 어렵지 만 코드에서 동적 SQL을 구축하려는 것은 매우 미숙하고 SQL injection 취약점에 취약합니다. –

답변

1

다음은 동적 크로스 탭을 사용하여이를 수행하는 방법입니다. 이것을 사용한다면 이것이 무엇을하는지 이해하도록하십시오. 마지막에 exec 앞에있는 행의 주석 처리를 제거하여 생성 된 동적 SQL을 볼 수 있습니다. 이 속성을 확장하여 다른 속성 속성 및 필요한 경우 새 열을 포함 할 수 있습니다.

if OBJECT_ID('tempdb..#Something') is not null 
    drop table #Something 

create table #Something 
(
    ItemRef nvarchar(48) 
    , AttributeID numeric(2, 0) 
    , AttributeName nvarchar(25) 
    , AttributeValue nvarchar(25) 
) 

insert #Something 
select 'Product123', 1, 'Brand', 'MyBrandName' union all 
select 'Product123', 2, 'Product Line', 'MyProductLine' union all 
select 'Product123', 3, 'Color', 'MyColor' union all 
select 'Product456', 1, 'Brand', 'MySecondBrandName' union all 
select 'Product456', 2, 'Style', 'MyStyle' 

declare @StaticPortion nvarchar(2000) = 
    'with OrderedResults as 
    (
     select *, ROW_NUMBER() over(partition by ItemRef order by ItemRef) as RowNum 
     from #Something 
    ) 
    select ItemRef'; 

declare @DynamicPortion nvarchar(max) = ''; 
declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by ItemRef order by ItemRef'; 

with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
cteTally(N) AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
) 

select @DynamicPortion = @DynamicPortion + 
    ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then AttributeName end) as AttributeName' + CAST(N as varchar(6)) + CHAR(10) 
    + ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then AttributeValue end) as AttributeValue' + CAST(N as varchar(6)) + CHAR(10) 
from cteTally t 
where t.N <= 
(
    select top 1 Count(*) 
    from #Something 
    group by ItemRef 
    order by COUNT(*) desc 
) 

declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion; 

--select @SqlToExecute 
exec sp_executesql @SqlToExecute 
관련 문제