2017-02-09 10 views
3

解決方案:如果沒有超出簡單查詢的範圍,我無法解決這個問題,所以我使用硬編碼case語句來達到表格數字標識符的極限。如何在不知道上限時使用聚合病例報告而不是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 

*編輯:下面是一些樣本數據:

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

這裏是我要的查詢結果:

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

起初我以爲使用一個PIVOT查詢,但在這裏運行了多個線程,這表明我嘗試了Aggregate Case語句,而這個語句的工作方式非常複雜乍一看效率。

但是,我不知道單個記錄有多少個屬性。所以我的問題是,如何編寫以下代碼以更好地表示不確定的屬性數量?

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注入漏洞。 –

回答

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 
相關問題