【问题标题】:Dynamic SQL Pivot - removing nulls动态 SQL Pivot - 删除空值
【发布时间】:2012-10-09 22:29:06
【问题描述】:

这是我第一次尝试在 SQL 中进行动态旋转,但我有点卡住了!

我有两张要加入的表格,一张保存库存商品,另一张保存不同网站(来源)的库存商品的不同价格。由于可能有不同的站点,因此查询需要是动态的。

问题是我无法从结果中删除空值,我希望有人能提供帮助。

目前的结果如下所示:

ID    site-site1   site-site2    site-site3
1      null          1.99          2.99
2      12.99         null          10.00
3      1.50          null          2.00

查询如下:

DECLARE @sources nvarchar(max)

SELECT @sources = 
STUFF(( SELECT DISTINCT ',[' + 
CASE 
WHEN ip.[Source] is null or ip.[Source] = '' THEN 'Default'
ELSE ip.[Source] 
END 
+ ' - ' +  
CASE 
WHEN ip.secondSource is null or ip.secondSource = '' THEN  'Default'
ELSE ip.secondSource 
END  
+ ']'
    FROM itemprice ip
    for XML PATH('')
  ), 1, 1, '')

DECLARE @SQL nvarchar(MAX)
SELECT @SQL = N'
SELECT *
FROM 
(
SELECT 
s.id, 
[Source] = CASE 
               WHEN ip.[Source] is null or ip.[Source] = '''' THEN  ''Default'' 
       ELSE ip.[Source] 
       END + '' - '' +  
CASE WHEN ip.secondSource is null or ip.secondSource = '''' THEN ''Default''
ELSE ip.secondSource 
END, 
    SalePrice = isnull(ip.SalePrice, 0)  
    FROM stock s 
    LEFT OUTER JOIN itemprice ip on ip.id = s.id
) data 
PIVOT 
( 
  MAX(SalePrice) for [Source] IN (' + @sources + ')
) as PivotTable
ORDER BY PivotTable.id'
exec sp_executesql @sql

任何帮助都将不胜感激,它似乎不像将每个 @sources 项目包装在 ISNULL 中那么简单。

谢谢

【问题讨论】:

  • 删除空值是什么意思?你想用什么来代替他们?
  • 对不起应该更清楚,在这种情况下我需要0s

标签: sql tsql pivot dynamic-sql


【解决方案1】:

不幸的是,您必须为每个单独的透视列设置 ISNULL。或者 CROSS JOIN 你的data 子查询来生成完整的矩阵并在那里执行 ISNULL。

例如在透视列上使用 ISNULL 将 NULL 替换为 0:

DECLARE @sources nvarchar(max), @Selectlist nvarchar(max)

SELECT @sources = 
STUFF(( SELECT DISTINCT ',[' + 
CASE 
WHEN ip.[Source] is null or ip.[Source] = '' THEN 'Default'
ELSE ip.[Source] 
END 
+ ' - ' +  
CASE 
WHEN ip.secondSource is null or ip.secondSource = '' THEN  'Default'
ELSE ip.secondSource 
END  
+ ']'
    FROM itemprice ip
    for XML PATH('')
  ), 1, 1, '')

SELECT @Selectlist = 
STUFF(( SELECT DISTINCT ',ISNULL([' + 
CASE 
WHEN ip.[Source] is null or ip.[Source] = '' THEN 'Default'
ELSE ip.[Source] 
END 
+ ' - ' +  
CASE 
WHEN ip.secondSource is null or ip.secondSource = '' THEN  'Default'
ELSE ip.secondSource 
END  
+ '],0) [' + 
CASE 
WHEN ip.[Source] is null or ip.[Source] = '' THEN 'Default'
ELSE ip.[Source] 
END 
+ ' - ' +  
CASE 
WHEN ip.secondSource is null or ip.secondSource = '' THEN  'Default'
ELSE ip.secondSource 
END  
+ ']'
    FROM itemprice ip
    for XML PATH('')
  ), 1, 1, '')

DECLARE @SQL nvarchar(MAX)
SELECT @SQL = N'
SELECT ID, ' + @Selectlist + '
FROM 
(
SELECT 
s.id, 
[Source] = CASE 
               WHEN ip.[Source] is null or ip.[Source] = '''' THEN  ''Default'' 
       ELSE ip.[Source] 
       END + '' - '' +  
CASE WHEN ip.secondSource is null or ip.secondSource = '''' THEN ''Default''
ELSE ip.secondSource 
END, 
    SalePrice = isnull(ip.SalePrice, 0)  
    FROM stock s 
    LEFT OUTER JOIN itemprice ip on ip.id = s.id
) data 
PIVOT 
( 
  MAX(SalePrice) for [Source] IN (' + @sources + ')
) as PivotTable
ORDER BY PivotTable.id'
exec sp_executesql @sql

【讨论】:

  • +1,但是,最好使用QUOTENAME(Column) 而不是'[' + column + ']'. If one of the dynamically created columns contains [` 或]QUOTENAME 会避免这种情况并尽可能确保输出有效用于选择的列。
  • 虽然说过我认为如果任何动态创建的列包含方括号,它将导致替换失败...也许分别为枢轴和选择生成列列表将是更强大的解决方案?
  • 透视列列表基本选择列列表。如果该解决方案适用于 OP,我不会对不包含 [] 的列名打赌。但是,是的,我个人使用QUOTENAME
  • 但解决方案不正确(刚刚修复) - ISNULL 会丢失所有列名,因此单独生成 SELECT/PIVOT 列似乎不可避免。
  • 非常感谢。我很感激可能有更好的方法来做到这一点,但是我很高兴能完成它!感谢 RichardTheKiwi。 GarethD 我现在每天都在使用 SQL,所以您的 cmets 也很有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2012-05-11
相关资源
最近更新 更多