【问题标题】:Sort Columns For Dynamic Pivot对动态透视的列进行排序
【发布时间】:2013-09-26 06:27:05
【问题描述】:

我有以下 SQL 查询,其中创建的列乱序,我不太确定如何修复它。

SELECT rhead.rhcust AS [Cust ID], rdetl.rdextp AS [Inv Amt], rhead.rhivdt AS [Inv Date]
INTO #TempTable
FROM rhead
LEFT OUTER JOIN rdetl
    ON rhead.rhinvc = rdetl.rdinvc
WHERE rhead.rhivdt >= '01-01-2012' AND rhead.rhivdt <= '12-25-12'

ALTER DATABASE Vista_TM SET COMPATIBILITY_LEVEL = 100

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Month'+cast(DATEPART(m, [Inv Date]) as varchar(2))) 
                    from #TempTable
            FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')

set @query = 'SELECT [Cust ID],' + @cols + ' 
            from 
            (
                SELECT [Cust ID], [Inv Amt],
                  ''Month''+cast(DATEPART(m, [Inv Date]) as varchar(2)) MonthNo
                FROM #TempTable
            ) x
            pivot 
            (
                sum([Inv Amt])
                for MonthNo in (' + @cols + ')
            ) p '

execute(@query)

DROP TABLE #TempTable

我认为这与查询的这一部分有关:

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Month'+cast(DATEPART(m, [Inv Date]) as varchar(2))) 
                    from #TempTable
            FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')

我确实尝试弄乱此topic 中发布的答案,但我无法运行查询。我希望有人可以提供帮助。

编辑我刚刚注意到我的行乱序,并且还想按 [客户 ID] 排序。

【问题讨论】:

  • 您的想法是对的,您可以在#TempTable 之后、FOR XML PATH('') 之前添加ORDER BY DATEPART(m, [Inv Date])。在一个不相关且不是很重要的注意事项上,我认为使用EXECUTE SP_EXECUTESQL @Query 而不是'EXECUTE(@Query)` 是更好的做法,Aaron Bertrand 也有blogged about it 在他的坏习惯中踢系列。跨度>

标签: sql sql-server-2008


【解决方案1】:

您可以通过在设置@cols 字符串时添加ORDER BY 来调整动态数据透视查询中的字段顺序:

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Month'+cast(DATEPART(m, [Inv Date]) as varchar(2))) 
                    from #TempTable
                    ORDER BY ....
            FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')

更新:起初错过了DISTINCT,当使用DISTINCT 时,您必须使用子查询,然后使用ORDER BY

SELECT @cols = STUFF((SELECT ',' +   QUOTENAME(ColName) 
                    FROM (SELECT DISTINCT 'Month'+cast(DATEPART(m, [Inv Date]) as varchar(2)) ColName
                          FROM #TempTable
                          )sub
                    ORDER BY ColName
                    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')

如果您不能简单地使用列名,您可能需要在子查询中添加一个“排序”字段,并且您可以将任何字段添加到子查询中,只要它们不会破坏DISTINCT 列表。例如:

SELECT @cols = STUFF((SELECT ',' +   QUOTENAME(ColName) 
                    FROM (SELECT DISTINCT 'Month'+cast(DATEPART(m, [Inv Date]) as varchar(2)) ColName
                                          ,CASE WHEN field = 'something' THEN 1
                                                WHEN field = 'something else' THEN 2
                                                ELSE 3
                                           END as Sort
                                          ,Cust_ID
                          FROM #TempTable
                          )sub
                    ORDER BY Sort,Cust_ID
                    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')

【讨论】:

  • 在我的特定示例中,我尝试了 ORDER BY [Inv Date]QUOTENAME 两者都不起作用,并且错误消息显示 如果指定了 SELECT DISTINCT,则 ORDER BY 项目必须出现在选择列表中。 我也试过[Inv Amt]
  • 这样,谢谢!不幸的是,我按月这样做,所以第 10、11、12 个月出现在第 1 个月之后。
  • 使用类似:ORDER BY CAST(REPLACE(ColName,'Month','')AS INT)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-07
相关资源
最近更新 更多