从该表中获取输出的行升序排列吗?

时间:2019-10-19 07:47:03

标签: sql sql-server tsql

我正在使用SQL Server 2014,下面的表格(t1)包含大约5,000行。 这是t1的摘录:

 n1   n2   n3   n4   n5   n6  Type
 6    15   10   11   22   25   C1
 2     5    1   20   21   30   C1
15    25   18    4   12   38   C2
11     1    4    9   24   31   C2
...

我需要从表中选择所有行,但是我希望输出以升序排列。

这是预期的输出:

 Nr1   Nr2   Nr3  Nr4   Nr5  Nr6   Type
  6    10    11   15    22   25     C1
  1     2     5   20    21   30     C1
  4    12    15   18    25   38     C2
  1     4     9   11    24   31     C2
  ...

我知道如何ORDER BY列,但是对于如何解决此问题我完全陷于困境。我是否需要pivot数据,对其进行排序然后再取消数据透视以实现此目的?

注意:我已将ID列添加到我的列中。现在每一行都有一个唯一的ID(1,2,3,...)

我根据Menno解决方案进行的尝试:

;with cte1 as (

SELECT [id], [type], Col, Val
FROM (  
  SELECT [id], [n1], [n2], [n3], [n4], [n5], [n6], [type]
  FROM [t1] ) t
UNPIVOT
   (Col FOR Val IN ([n1], [n2], [n3], [n4], [n5], [n6]))
AS tblUnPivot

),

cte2 as (

Select

ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Val) OrderedVals, * 

from [cte1]

),

cte3 as (

SELECT [id], [type], Col, Val
FROM (  
  SELECT [OrderedVals], [id], [type], [Col]
  FROM [cte2] ) s
PIVOT
   (??? FOR OrderedVals IN ([1],[2],[3],[4],[5],[6]))

AS tblPivot

)

select * from [cte3]

4 个答案:

答案 0 :(得分:4)

假定,其中有某种ID列,然后您可以取消透视值,然后使用VALUES和一个交叉表将其透视回去:

CREATE TABLE dbo.YourTable (ID int IDENTITY, --Required to work
                            n1 tinyint,
                            n2 tinyint,
                            n3 tinyint,
                            n4 tinyint,
                            n5 tinyint,
                            n6 tinyint,
                            [Type] char(2));
GO

INSERT INTO dbo.YourTable (n1,n2, n3, n4, n5, n6, [Type])
VALUES( 6,15,10,11,22,25,'C1'),
      ( 2, 5, 1,20,21,30,'C1'),
      (15,25,18, 4,12,38,'C2'),
      (11, 1, 4, 9,24,31,'C2');

GO

SELECT *
FROM dbo.YourTable;

WITH unPvt AS (
    SELECT YT.ID,
           YT.[Type],
           V.Val,
           ROW_NUMBER() OVER (PARTITION BY YT.ID ORDER BY V.Val) AS NewPos
    FROM dbo.YourTable YT
         CROSS APPLY (VALUES(1,YT.n1),
                            (2,YT.n2),
                            (3,YT.n3),
                            (4,YT.n4),
                            (5,YT.n5),
                            (6,YT.n6))V(Pos,Val))
SELECT MAX(CASE NewPos WHEN 1 THEN Val END) AS n1,
       MAX(CASE NewPos WHEN 2 THEN Val END) AS n2,
       MAX(CASE NewPos WHEN 3 THEN Val END) AS n3,
       MAX(CASE NewPos WHEN 4 THEN Val END) AS n4,
       MAX(CASE NewPos WHEN 5 THEN Val END) AS n5,
       MAX(CASE NewPos WHEN 6 THEN Val END) AS n6,
       [Type]
FROM unPvt
GROUP BY ID,[Type]
ORDER BY [Type];


GO
DROP TABLE dbo.YourTable;

答案 1 :(得分:1)

  • 您可以为每一行赋予唯一的ID,例如:ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) ID
  • 然后您可以取消数据透视,例如:Col FOR Val IN ([Nr1], [Nr2], [Nr3], [Nr4], [Nr5], [Nr 6])
  • 然后订购每个ID的值,例如:ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Val) OrderedVals
  • 然后旋转数据FOR OrderedVals IN ([1],[2],[3],[4],[5],[6])

答案 2 :(得分:1)

这类似于Larnu的回答,但它应该具有更好的性能,因为它避免了整个表的聚集。此外,它返回与原始数据相同的行,而不会引入伪造的def save(self,*args,**kwargs): total_records = About.objects.count() if total_records >= 2: raise DbLimitException({"message": "Db limit reached please delete to add more data"}) else: super().save(*args,**kwargs)

您可以在id内进行汇总:

CROSS APPLY

答案 3 :(得分:0)

您可以在不使用数据透视的情况下使用此代码

DECLARE @T 
TABLE(n1 INT, n2 INT, n3 INT, n4 INT, n5 INT, n6 INT,Type VARCHAR(10))

INSERT INTO @T(n1,   n2,   n3,   n4,   n5,   n6,  Type)
      SELECT  6  ,  15  , 10  , 11 , 22  , 25  , 'C1'
UNION SELECT  2  ,  5   , 1   , 20 , 21  , 30  , 'C1'
UNION SELECT  15 ,  25  , 18  , 4  , 12  , 38  , 'C2'
UNION SELECT  11 ,  1   , 4   , 9  , 24  , 31  , 'C2'

SELECT SUM(CASE WHEN ord=1 THEN n ELSE 0 END) AS Nr1,
       SUM(CASE WHEN ord=2 THEN n ELSE 0 END) AS Nr2,
       SUM(CASE WHEN ord=3 THEN n ELSE 0 END) AS Nr3,
       SUM(CASE WHEN ord=4 THEN n ELSE 0 END) AS Nr4,
       SUM(CASE WHEN ord=5 THEN n ELSE 0 END) AS Nr5,
       SUM(CASE WHEN ord=6 THEN n ELSE 0 END) AS Nr6,
       Type
FROM (SELECT *,ROW_NUMBER()OVER(ORDER by Type) as unq
      FROM @T
)AS IndexedT
CROSS APPLY(SELECT n , ROW_NUMBER()OVER(ORDER by n) as ord
            FROM (      SELECT n1 as n 
                  UNION SELECT n2       
                  UNION SELECT n3      
                  UNION SELECT n4       
                  UNION SELECT n5       
                  UNION SELECT n6      
            )as X
) AS PivotItem
GROUP BY unq,Type