解决方案:我无法在不超出简单查询的情况下解决这个问题,因此我已经将案例陈述硬编码到我表格的数字标识符的极限。
我正在寻找帮助,编写一个查询来表示多个字段中的未知数量的记录,每个主键只有一条记录。
这是我的餐桌设计:
[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
答案 0 :(得分: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