使用多个 UNION 重写 SQL Server 查询

Posted

技术标签:

【中文标题】使用多个 UNION 重写 SQL Server 查询【英文标题】:Rewriting SQL Server query with multiple UNIONs 【发布时间】:2012-12-17 20:19:23 【问题描述】:

有没有更好(更有效)的方式来编写这个查询?似乎应该有一种方法可以只用一个UNION 来编写它。

查询:

SELECT 'Value1' as PropertyKey, PropertyValue=(SELECT Value1 FROM MyTable WITH (NOLOCK))
UNION
SELECT 'Value2' as PropertyKey, PropertyValue=(SELECT Value2 FROM MyTable WITH (NOLOCK))
UNION
SELECT 'Value3' as PropertyKey, PropertyValue=(SELECT Value3 FROM MyTable WITH (NOLOCK))
UNION
...
SELECT 'Value100' as PropertyKey, PropertyValue=(SELECT Value100 FROM MyTable WITH (NOLOCK))

最终,我需要我的结果集有 2 列(PropertyKeyPropertyValue)。 PropertyKey 列中的值将是我的表中列的名称,PropertyValue 列中的值将是相应的值。

如果我总是从同一张表中选择,是否可以只用一个UNION 来写这个?

【问题讨论】:

【参考方案1】:

如果您可以访问UNPIVOT 函数,您可以通过以下方式使用它:

select PropertyKey, PropertyValue
from yourtable
unpivot
(
  PropertyValue
  for PropertyKey in (Value1, Value2, Value3) -- list other columns here
) unpiv

UNPIVOT 要记住的关键是数据类型必须相同,因此您可能需要转换数据类型:

select PropertyKey, PropertyValue
from
(
    select CAST(value1 as varchar(10)), 
         CAST(value1 as varchar(10)), ...
    from yourtable
) src
unpivot
(
  PropertyValue
  for PropertyKey in (Value1, Value2, Value3) -- list other columns here
) unpiv

您甚至可以动态执行此操作,这将在运行时获取要转换的列列表:

DECLARE @colsUnpivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)    

select @colsUnpivot = stuff((select ','+quotename(C.name)
         from sys.columns as C
         where C.object_id = object_id('yourtable')
         for xml path('')), 1, 1, '')

set @query 
  = 'select PropertyKey, PropertyValue
     from yourtable
     unpivot
     (
        PropertyValue
        for PropertyKey in ('+ @colsunpivot +')
     ) u'

exec(@query)

如果您卡住了,使用您当前的版本,那么我会稍微改变它并使用UNION ALL 而不是UNION

SELECT 'Value1' as PropertyKey, Value1 PropertyValue
FROM MyTable
UNION ALL
SELECT 'Value2' as PropertyKey, Value2 PropertyValue
FROM MyTable

【讨论】:

感谢您的回复!如果我没有名为 PropertyKey 和 PropertyValue 的列,那么 unpivot 示例是否有效?这些不是我的实际列名,但我需要以这种方式返回它们。例如,我的结果集将包含一个名为 PropertyKey 的列,其中的所有记录都将我的实际列名作为 PropertyKey 列中的值返回。希望这是有道理的。 @lhan16 PropertyKey 将显示列的名称,PropertyValue 将具有每列的值。 谢谢。我收到的错误是“列 'Value1' 的类型与 UNPIVOT 列表中指定的其他列的类型冲突。”如果我的列类型不同,我需要做任何类型的转换吗? @lhan16 是的,数据类型必须相同才能执行 unpivot,请参阅我的编辑

以上是关于使用多个 UNION 重写 SQL Server 查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server-聚焦UNIOL ALL/UNION查询

SQL Server函数?

sql server 中union的用法

sql server 中union的用法?

SQL Server 是不是可以使用 PHP 从 UNION 查询中返回不同的别名列名?

sql server的exists,union,union all