如何创建一个表来表示给定表的所有列的最小值和最大值?

时间:2015-04-16 17:05:38

标签: sql sql-server tsql

我想知道是否可以按如下方式创建汇总表。给出一个表格,例如

Id | Age | Banksaldo | Number of children | Car owner
1  | 27  | 2000      | 5                  | No
2  | 30  | 3000      | 2                  | Yes

应该变成:

Column name | Minimum | Minimum Id | Maximum | Maximum Id
Age         | 27      | 1          | 30      | 2
Banksaldo   | 2000    | 1          | 3000    | 2
Number of...| 2       | 2          | 5       | 1

具体来说,我在调用SQL语句然后将其插入新表时遇到问题。另外,我也遇到了以上面指定格式创建它的问题。

有人可以给我一些关于如何解决这个问题的提示吗?

感谢您的努力。

PS:我使用的是Microsoft SQL Server 2014。

2 个答案:

答案 0 :(得分:2)

作为第一步,您可以使用UNPIVOT

 SELECT Id, [Column Name], Columns
   FROM 
     (SELECT Id, Age, Banksaldo, [Number of children]
      FROM mytable) p
   UNPIVOT
      (Columns FOR [Column Name] IN (Age, Banksaldo, [Number of children])
   )AS unpvt 

获取以下结果集:

Id  Column Name         Columns
--------------------------------
1   Age                 27
1   Banksaldo           2000
1   Number of children  5
2   Age                 30
2   Banksaldo           3000
2   Number of children  2

在上面的派生表上使用ROW_NUMBER以便找到最小/最大记录:

SELECT Id, [Column Name], Columns,
       ROW_NUMBER() OVER (PARTITION BY [Column Name] 
                          ORDER BY Columns) AS minRn,
       ROW_NUMBER() OVER (PARTITION BY [Column Name] 
                          ORDER BY Columns DESC) AS maxRn
FROM (
  ... unpivot query here ...
) t 

从上方输出

 Id Column Name         Columns minRn   maxRn
-----------------------------------------------
2   Age                 30      2       1
1   Age                 27      1       2
2   Banksaldo           3000    2       1
1   Banksaldo           2000    1       2
1   Number of children  5       2       1
2   Number of children  2       1       2

最后一步,您可以在minRnmaxRn上使用条件聚合来获取所需的结果集:

SELECT [Column Name], 
       MAX(CASE WHEN minRn = 1 THEN Id END) AS [Minimum Id],
       MAX(CASE WHEN minRn = 1 THEN Columns END) AS [Minimum],
       MAX(CASE WHEN maxRn = 1 THEN Id END) AS [Maximum Id],
       MAX(CASE WHEN maxRn = 1 THEN Columns END) AS [Maximum]
FROM ( 
  SELECT Id, [Column Name], Columns, minRn, maxRn
  FROM (
  SELECT Id, [Column Name], Columns,
         ROW_NUMBER() OVER (PARTITION BY [Column Name] 
                            ORDER BY Columns) AS minRn,
         ROW_NUMBER() OVER (PARTITION BY [Column Name] 
                            ORDER BY Columns DESC) AS maxRn
  FROM (
     SELECT Id, [Column Name], Columns
     FROM 
       (SELECT Id, Age, Banksaldo, [Number of children]
        FROM mytable) p
     UNPIVOT
        (Columns FOR [Column Name] IN (Age, Banksaldo, [Number of children])
     )AS unpvt ) t 
) s
WHERE s.minRn = 1 OR s.maxRn = 1 ) u
GROUP BY [Column Name]

SQL Fiddle Demo

答案 1 :(得分:2)

我认为这是最简单的方法,而且非常有效。大多数人都不使用CROSS APPLY,这在这个解决方案中非常有效。

DECLARE @yourTable TABLE (ID INT,Age INT, BankSaldo INT,[Number of Children] INT,[Car Owner] CHAR(3))
INSERT INTO @yourTable 
VALUES  (1,27,2000,5,'No'),
        (2,30,3000,2,'Yes');

WITH CTE_Unpivot
AS
(
    SELECT ID,col,val
    FROM @yourTable
    UNPIVOT
    (
        val for col IN ([Age],[BankSaldo],[Number Of Children])
    ) unpvt
)

SELECT DISTINCT col AS [Column Name],
                MinCA.val AS Minimum,
                MinCA.ID AS [Minimum ID],
                MaxCA.val AS [Maximum],
                MaxCA.ID AS [Maximum ID]
FROM CTE_Unpivot A
CROSS APPLY (SELECT TOP 1 val,ID FROM CTE_Unpivot WHERE col = A.col ORDER BY val) MinCA
CROSS APPLY (SELECT TOP 1 val,ID FROM CTE_Unpivot WHERE col = A.col ORDER BY val DESC) MaxCA

结果:

Column Name               Minimum     Minimum ID  Maximum     Maximum ID
------------------------- ----------- ----------- ----------- -----------
Age                       27          1           30          2
BankSaldo                 2000        1           3000        2
Number of Children        2           2           5           1