[英]Dynamic Multi-Column SQL
I have two tables with structures like this: 我有两个具有如下结构的表:
Aisle | 过道| ItemId | ItemId | ConfigId | ConfigId | InventSizeId | InventSizeId | InventColorId | InventColorId | InventLocationId | InventLocationId | DataAreaId | DataAreaId | VelocityCategory VelocityCategory
ItemId | ItemId | ConfigId | ConfigId | InventSizeId | InventSizeId | InventColorId | InventColorId | InventLocationId | InventLocationId | DataAreaId | DataAreaId | Sales 销售
Every row in the Base table represents a SKU and the sum of the related SalesCount records' "Sales" fields determines the "Picks". 基本表中的每一行都代表一个SKU,并且相关SalesCount记录的“销售”字段的总和决定了“选择”。 This query works: 该查询有效:
SELECT Aisle, COUNT(*) as '# SKUs',
SUM(Sales) as '# Picks',
SUM(CASE WHEN VelocityCategory = 'Hot' THEN 1 ELSE 0 END) as 'Hot SKUs',
SUM(CASE WHEN VelocityCategory = 'Hot' THEN SALES ELSE 0 END) as 'Hot Picks',
SUM(CASE WHEN VelocityCategory = 'Warm' THEN 1 ELSE 0 END) as 'Warm SKUs',
SUM(CASE WHEN VelocityCategory = 'Warm' THEN SALES ELSE 0 END) as 'Warm Picks',
SUM(CASE WHEN VelocityCategory = 'Cold' THEN 1 ELSE 0 END) as 'Cold SKUs',
SUM(CASE WHEN VelocityCategory = 'Cold' THEN SALES ELSE 0 END) as 'Cold Picks'
FROM [dbo].[VelocityBase] Base
LEFT OUTER JOIN [dbo].[VelocitySalesCount] SalesCount
ON Base.ItemId = SalesCount.ItemId
AND Base.ConfigId = SalesCount.ConfigId
AND Base.InventSizeId = SalesCount.InventSizeId
AND Base.InventColorId = SalesCount.InventColorId
AND Base.InventLocationId = SalesCount.InventLocationId
AND SalesCount.DataAreaId = Base.DataAreaId
GROUP BY Aisle
ORDER BY Aisle
However, the columns are hard coded. 但是,这些列是硬编码的。 What I would like is that the "Hot", "Warm", "Cold", etc be generated based on what values are present in the database for this column. 我想要的是根据数据库中该列中存在的值来生成“热”,“暖”,“冷”等。 That way if a user added a row that had "Lukewarm" as the VelocityCategory, two new columns would appear with that data. 这样,如果用户添加了以“ Lukewarm”作为行速类别的行,则该数据将出现两个新列。
I'm not sure if something like SQL to generate SQL or maybe a PIVOT function would do the trick. 我不确定是否可以使用类似SQL的方法来生成SQL或PIVOT函数。
Thanks in advance! 提前致谢!
EDIT: 编辑:
I'm narrowing in. I've got the Sum of the Sales figures using this: 我正在缩小范围。使用以下方法可以得出“销售总额”数据:
DECLARE @SQLStatement NVARCHAR(4000)
,@PivotValues NVARCHAR(4000);
SET @PivotValues = '';
SELECT @PivotValues = @PivotValues + ',' + QUOTENAME(VelocityCategory)
FROM
(
SELECT DISTINCT VelocityCategory
FROM dbo.VelocityBase
) src;
SET @PivotValues = SUBSTRING(@PivotValues,2,4000);
SELECT @SQLStatement =
'SELECT pvt.*
FROM
(
SELECT Aisle, VelocityCategory, Sales
FROM VelocityBase Base
LEFT OUTER JOIN [dbo].[VelocitySalesCount] SalesCount
ON Base.ItemId = SalesCount.ItemId
AND Base.ConfigId = SalesCount.ConfigId
AND Base.InventSizeId = SalesCount.InventSizeId
AND Base.InventColorId = SalesCount.InventColorId
AND Base.InventLocationId = SalesCount.InventLocationId
AND SalesCount.DataAreaId = Base.DataAreaId
) VelocityBase
PIVOT ( Sum(Sales) FOR VelocityCategory IN ('+@PivotValues+') ) pvt';
EXECUTE sp_executesql @SQLStatement;
Thanks for the link to the previous question which got me this far. 感谢您到上一个问题的链接,这使我到现在为止。
I usually do not use PIVOT, just "usual" dynamic SQL like this: 我通常不使用PIVOT,而只是使用“通常”的动态SQL,如下所示:
DECLARE @sSQL NVARCHAR(MAX)= '' ,
@sSQLSum NVARCHAR(MAX)= '' ,
@sSQlBegin NVARCHAR(MAX)= '
SELECT Aisle, COUNT(*) As ''# SKUs'',
SUM(Sales) As ''# Picks'',
' ,
@sSQLEnd NVARCHAR(MAX)= 'FROM [Dbo].[VelocityBase] Base
LEFT OUTER JOIN [Dbo].[VelocitySalesCount] SalesCount
ON Base.ItemId = SalesCount.ItemId
AND Base.ConfigId = SalesCount.ConfigId
AND Base.InventSizeId = SalesCount.InventSizeId
AND Base.InventColorId = SalesCount.InventColorId
AND Base.InventLocationId = SalesCount.InventLocationId
AND SalesCount.DataAreaId = Base.DataAreaId
GROUP BY Aisle
ORDER BY Aisle' ;
WITH c AS ( SELECT DISTINCT
VelocityCategory N
FROM Dbo.VelocityBase
)
SELECT @sSQLSum = @sSQLSum + 'SUM(CASE WHEN c.N=''' + c.N
+ ''' THEN 1 ELSE 0 END ) AS ''' + c.N + ' SKUs'',' + CHAR(13)
+ 'SUM(CASE WHEN c.N=''' + c.N
+ ''' THEN SALES ELSE 0 END ) AS ''' + c.N + ' Sales'',' + CHAR(13)
FROM c
IF(LEN(@sSQLSum))>0
SET @sSQLSum = LEFT(@sSQLSum, ( LEN(@sSQLsum) - 2 ))
SET @sSQL = @sSQlBegin + @sSQLSum + CHAR(13) + @sSQLEnd
EXEC (@sSQL)
Unless you generate the query dynamically, I don't think there's a way to generate what you want. 除非您动态生成查询,否则我认为没有一种生成所需内容的方法。
Your problem could be solved easily if your tables were normalized. 如果您的表已标准化,则可以轻松解决您的问题。 For instance, the VelocityBase
table should have a VelocityCategoryID
column instead of a VelocityCategory
column. 例如, VelocityBase
表应具有VelocityCategoryID
列而不是VelocityCategory
列。 This new column should be a foreign key
to a new table called VelocityCategory
(or something like that) then your query for this calculation becomes almost trivial. 此新列应该是名为VelocityCategory
(或类似名称)的新表的foreign key
,因此您对此计算的查询几乎变得无关紧要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.