我在 SQL Server 中有一个表,其中的行如下:
ID(整数) | 名称(varchar) | 已启用(int) | 对象名称(varchar) | 属性名称(varchar) | 属性值字符串(varchar) | PropertyValueInt |
---|---|---|---|---|---|---|
1 | 规则01 | 1 | 我的对象 | 空 | 空 | 空 |
2 | 规则02 | 1 | 我的对象 | 空 | 空 | 空 |
3 | 规则03 | 1 | 我的对象 | 空 | 空 | 空 |
4 | 规则04 | 1 | 我的对象 | 空 | 空 | 空 |
5 | 规则05 | 1 | 我的对象 | 空 | 空 | 空 |
6 | 提案01 | 0 | 我的对象 | 提案01 | $ | 空 |
7 | 提案02 | 0 | 我的对象 | 提案02 | 空 | 45 |
我编写了这个存储过程,它根据传入的
ObjectName
参数动态地将行旋转为列:
DECLARE @cols AS NVARCHAR(MAX)='';
DECLARE @query AS NVARCHAR(MAX)='';
SELECT
@cols = @cols + QUOTENAME(Name) + ','
FROM
(SELECT DISTINCT Name
FROM ItemsTable
WHERE LOWER(ObjectName) = LOWER(@objectName)
GROUP BY Name) AS tmp
SELECT @cols = SUBSTRING(@cols, 0, LEN(@cols))
SET @query =
'SELECT * FROM
(
SELECT
[Name]
,CAST([IsEnabled] AS VARCHAR(50)) as [ValueColumn]
,[ObjectName]
FROM ItemsTable
UNION
SELECT
[Name]
,[PropertyValueString] as [ValueColumn]
,[ObjectName]
FROM ItemsTable
UNION
SELECT
[Name]
,CAST([PropertyValueInt] AS VARCHAR(50)) as [ValueColumn]
,[ObjectName]
FROM ItemsTable
) src
pivot
(
max(ValueColumn) for Name in (' + @cols + ')
) piv'
返回的值之一不正确,特别是对于
Prop01
。我期待返回“$”,但得到的是 0
。
如何修复此错误?
嗯,字符
'0'
的排序高于 '$'
,因此 '0'
对于给定的逻辑是正确的。如果您想将 IsEnabled = 0
视为微不足道,也许您希望在联合的第一部分中使用 NULLIF([IsEnabled], 0)
。您的 PropertyValueInt
专栏可能需要类似的内容。
或者您希望 id 将零视为空字符串(而不是 null),您可以尝试
ISNULL(CAST(NULLIF([IsEnabled], 0) AS VARCHAR(50)), '''')
(动态 SQL 字符串的引号加倍)。
另一种方法是删除
UNION
并使用 CROSS APPLY
为每行选择适当的源值。
SET @query =
'SELECT * FROM
(
SELECT
I.Name
,V.ValueColumn
,I.ObjectName
FROM ItemsTable I
CROSS APPLY (
SELECT COALESCE(
I.PropertyValueString,
CAST(I.PropertyValueInt AS VARCHAR(50)),
CAST(I.IsEnabled AS VARCHAR(50))
) AS ValueColumn
) V
) src
pivot
(
max(ValueColumn) for Name in (' + @cols + ')
) piv'
这假设每行不超过一个
PropertyValue*
列为非空,并且 IsEnabled
仅在所有属性值为空时适用。您可以根据需要进一步调整逻辑。
看到这个db<>小提琴。