0

我的问题实际上是如何确保在使用动态查询获取数据时保持 OUTPUT 的 ORDER。我有几个正在使用的动态查询,我注意到当我在不同的机器上运行相同的查询时,我得到的输出顺序不同。目前,我将输出的数据存储到一个临时表中,该表假定输出的顺序与我本地机器上的顺序相同,但在生产中,它全部被打开。如何对此进行更多控制,以便每次运行查询时都保持输出顺序?

当我在动态查询中使用 Order BY 时,出现错误

消息 1033,级别 15,状态 1,第 18 行 ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效,除非还指定了 TOP、OFFSET 或 FOR XML。

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

           IF EXISTS
                (
                            SELECT *
                            FROM tempdb.dbo.sysobjects
                            WHERE ID = OBJECT_ID(N'tempdb..#ibutes')
                )
                BEGIN
                            DROP TABLE #ibutes
                END
    Create table #ibutes
    (
                ProductID uniqueIdentifier,
            PAID uniqueidentifier, 
            Label nvarchar(50),
            Val nvarchar(3072),
            unit nvarchar(50) 
    )
    ;With Number
As
(
 Select 1 as rownum union all  Select 2 union all Select 3 union all Select 4 union all Select 5 union all Select 6 union all Select 7 union all Select 8 union all Select 9 union all Select 10 union all Select 11 union all Select 12 union all Select 13 union all Select 14 union all Select 15 union all Select 16 union all Select 17 union all Select 18 union all Select 19 union all Select 20 union all Select 21 
),
ProductDetail 
as 
(
   select P.ProdID, N.rownum from IDWProduct P cross join Number N
)
Insert into #ibutes
Select ProdID ,  PAVibuteID, COALESCE(PANAme,''), COALESCE(PAVValue,''), COALESCE(unitLabel,'') 
 from ProductDetail P
Left join 
(select Pr.*, PAName, row_number() over (partition by PAVProductID order by PAVID) as Rn from IDWProductibuteValues Pr  
inner join IDWibutes  on PAID = PAVibuteID Where PAIscustom = 0 AND PAIsManufacturerSpecific =0 AND PANAME NOT IN 
('Brand Name', 'Standard', 'Application', 'Sub Brand', 'Type', 'Special Features')) 
Pr ON rownum = Pr.Rn And PAVProductID = ProdID  
left join IDWUnitofMeasures on Pr.PAVunit = unitID 

--Select * from #ibutes

   select @colsUnpivot = stuff((select ','+quotename(C.name)
         from tempdb.sys.columns as C  
         where C.object_id = object_id('tempdb..#ibutes')  AND  C.name Not in ('ProductID')
         for xml path('')), 1, 1, '')

 --select @colsUnpivot

 select @colsPivot = STUFF((SELECT  ','  + quotename(c.name   + cast(t.rn as varchar(10)))
                    from
                    (
                      select row_number() over(partition by ProductID   order by ProductID) rn  from #ibutes
                    ) t
                     cross apply 
                      tempdb.sys.columns  as C
                   where C.object_id = object_id('tempdb..#ibutes')   AND  C.name Not in ('ProductID')
                   group by c.name, t.rn
                   order by t.rn
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

  --select @colsPivot
  set @query = 'select *
      from
      (
        select ProductID,
            col + cast(rn as varchar(10)) new_col,
            val
        from 
        (
          select   
           Cast (PAID as NVarchar(3072)) PAID
           ,Cast (ProductID as NVarchar(3072)) ProductID
           ,Cast (Label  as NVarchar(3072)) Label
           ,Cast (Val as NVarchar(3072)) Val
           ,Cast (unit as NVarchar(3072))  unit  
            ,row_number() over(partition by ProductID order by ProductID) rn
          from #ibutes

     ) x
        unpivot
        (
          val
          for col in ('+ @colsunpivot +')
        ) u
      ) x1
      pivot
      (
        max(val)
        for new_col in
          ('+ @colspivot +')
      ) p'

exec(@query)    

运行查询的结果

在我的本地/开发机器上

=========================

select *
      from
      (
        select ProductID,
            col + cast(rn as varchar(10)) new_col,
            val
        from 
        (
          select   
       Cast (PAID as NVarchar(3072)) PAID
       ,Cast (ProductID as NVarchar(3072)) ProductID
           ,Cast (Label  as NVarchar(3072)) Label
           ,Cast (Val as NVarchar(3072)) Val
           ,Cast (unit as NVarchar(3072))  unit  
            ,row_number() over(partition by ProductID order by ProductID) rn
          from #ibutes
     ) x
        unpivot
        (
          val
          for col in ([Label],[unit],[Val],[PAID])
        ) u
      ) x1
      pivot
      (
        max(val)
        for new_col in
          ([Label1],[unit1],[Val1],[PAID1],[Label2],[unit2],[Val2],[PAID2],[Label3],[unit3],[Val3],[PAID3],[Label4],[unit4],[Val4],[PAID4],[Label5],[unit5],[Val5],[PAID5],[Label6],[unit6],[Val6],[PAID6],[Label7],[unit7],[Val7],[PAID7],[Label8],[unit8],[Val8],[PAID8],[Label9],[unit9],[Val9],[PAID9],[Label10],[unit10],[Val10],[PAID10],[Label11],[unit11],[Val11],[PAID11],[Label12],[unit12],[Val12],[PAID12],[Label13],[unit13],[Val13],[PAID13],[Label14],[unit14],[Val14],[PAID14],[Label15],[unit15],[Val15],[PAID15],[Label16],[unit16],[Val16],[PAID16],[Label17],[unit17],[Val17],[PAID17],[Label18],[unit18],[Val18],[PAID18],[Label19],[unit19],[Val19],[PAID19],[Label20],[unit20],[Val20],[PAID20],[Label21],[unit21],[Val21],[PAID21])
      ) p 

在生产机器上,但它是不同的。请注意更改顺序

select *
      from
      (
        select ProductID,
            col + cast(rn as varchar(10)) new_col,
            val
        from 
        (
          select   
       Cast (PAID as NVarchar(3072)) PAID
       ,Cast (ProductID as NVarchar(3072)) ProductID
           ,Cast (Label  as NVarchar(3072)) Label
           ,Cast (Val as NVarchar(3072)) Val
           ,Cast (Unit as NVarchar(3072))  Unit  
            ,row_number() over(partition by ProductID order by ProductID) rn
          from #ibutes
     ) x
        unpivot
        (
          val
          for col in ([PAID],[Label],[Val],[Unit])
        ) u
      ) x1
      pivot
      (
        max(val)
        for new_col in
          ([PAID1],[Label1],[Val1],[Unit1],[PAID2],[Label2],[Val2],[Unit2],[PAID3],[Label3],[Val3],[Unit3],[PAID4],[Label4],[Val4],[Unit4],[PAID5],[Label5],[Val5],[Unit5],[PAID6],[Label6],[Val6],[Unit6],[PAID7],[Label7],[Val7],[Unit7],[PAID8],[Label8],[Val8],[Unit8],[PAID9],[Label9],[Val9],[Unit9],[PAID10],[Label10],[Val10],[Unit10],[PAID11],[Label11],[Val11],[Unit11],[PAID12],[Label12],[Val12],[Unit12],[PAID13],[Label13],[Val13],[Unit13],[PAID14],[Label14],[Val14],[Unit14],[PAID15],[Label15],[Val15],[Unit15],[PAID16],[Label16],[Val16],[Unit16],[PAID17],[Label17],[Val17],[Unit17],[PAID18],[Label18],[Val18],[Unit18],[PAID19],[Label19],[Val19],[Unit19],[PAID20],[Label20],[Val20],[Unit20],[PAID21],[Label21],[Val21],[Unit21])
      ) p

请注意顺序似乎按字母顺序排列的本地机器的区别

[标签 1],[单位 1],[Val1],[PAID1],[标签 2],[单位 2]。 . . .

在生产机器上,它不是

[PAID1],[Label1],[Val1],[Unit1],[PAID2],[Label2],[Val2],[Unit2],... . .

4

7 回答 7

1

我认为只有一个显而易见的答案。在动态查询中使用该order by子句。

于 2012-10-14T17:51:09.807 回答
1

简而言之,不保证所有查询(无论是否动态)在不同机器上的结果都是一样的!
如果结果的顺序对您很重要,请使用ORDER BY

例如:

SELECT *
FROM TBL
ORDER BY FIRSTNAME
于 2012-10-14T17:51:16.130 回答
1

如果您要订购,请使用 order by。
如果没有订单,则无法保证订单。
如果有平局,则不能保证排序会在平局上重复。
使用足够多的列没有平局。

看来您指的是列的顺序而不是行的顺序。

如果选择 *,您将按照在表中定义的顺序排列列。
如果您需要控制列的顺序,请不要使用 *.

select table1.col4, table1.col2 
from table1
于 2012-10-14T17:51:45.080 回答
0

你可以试试下面的吗?

将以下顺序添加到第一个查询中

select @colsUnpivot = stuff((select ','+quotename(C.name)
     from tempdb.sys.columns as C  
     where C.object_id = object_id('tempdb..#ibutes')  AND  C.name Not in ('ProductID')

ORDER BY c.column_id --Add this

     for xml path('')), 1, 1, '')

通过以下第二个查询更改顺序

select @colsPivot = STUFF((SELECT  ','  + quotename(c.name   + cast(t.rn as varchar(10)))
                from
                (
                  select row_number() over(partition by ProductID   order by ProductID) rn  from #ibutes
                ) t
                 cross apply 
                  tempdb.sys.columns  as C
               where C.object_id = object_id('tempdb..#ibutes')   AND  C.name Not in ('ProductID')
               group by c.name, t.rn

               ORDER BY c.column_id --Change this

        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

希望有帮助...

于 2014-12-13T00:00:07.603 回答
0

为什么不更改以下内容:

set @query = 'select *
      from

类似于

set @query = 'select *
      into #x
      from

您需要#x在动态 sql ie 之前显式创建

create table #x
(
blah int,
blah char(8)
)

然后在exec语句之后有一个进一步的查询

select *
from #x
order by whatever 
于 2012-10-14T19:33:37.583 回答
0

现在我们知道您在哪里添加 ORDER BY,答案就更清楚了。您正在尝试对其结果插入@colsPivot 的查询进行排序,这就是问题所在。

ORDER BY 主要用于对最终结果进行排序,因此应该在最终查询(动态查询)上。
例外情况是,如果它被用作“限制”查询的一部分(例如 TOP 10)。

尝试将 ORDER BY 添加到动态查询中,让我们知道它是否有效。

于 2012-10-14T18:37:51.803 回答
0

也许你可以试试这个

'select *
  from
  (
    select ProductID,
        col + cast(rn as varchar(10)) new_col,
        val
    from 
    (
      select top 100 percent
       Cast (PAID as NVarchar(3072)) PAID
       ,Cast (ProductID as NVarchar(3072)) ProductID
       ,Cast (Label  as NVarchar(3072)) Label
       ,Cast (Val as NVarchar(3072)) Val
       ,Cast (unit as NVarchar(3072))  unit  
        ,row_number() over(partition by ProductID order by ProductID) rn
      from #ibutes
      order by row_number() over(partition by ProductID order by ProductID) asc
 ) x
    unpivot
    (
      val
      for col in ('+ @colsunpivot +')
    ) u
  ) x1
  pivot
  (
    max(val)
    for new_col in
      ('+ @colspivot +')
  ) p'
于 2012-10-14T18:21:29.900 回答