【问题标题】:SQL: Pick highest and lowest value (int) from one rowSQL:从一行中选择最高和最低值(int)
【发布时间】:2017-04-13 13:31:25
【问题描述】:

我正在寻找一种从表中的单行中选择最高和最低值(整数)的方法。我需要将 4 列一起比较并获得最高和最低的数字。

表格看起来像这样......

id | name | col_to_compare1 | col_to_compare2 | col_to_compare3 | col_to_compare4

1 | John | 5 | 5 | 2 | 1

2 | Peter | 3 | 2 | 4 | 1

3 | Josh | 3 | 5 | 1 | 3

你能帮帮我吗?谢谢!

【问题讨论】:

  • 想要的输出是什么?
  • 另一列具有最高值,下一列具有最低值。
  • 这是数据模型损坏的标志 - 如果您有想要比较或计算聚合的值,这表明它们是相同的值“类型”并且应该存储在单列中(跨多行)。此外,您的一些数据 (1,2,3,4)(如果确实相关)已嵌入到不太容易查询的 元数据 中。

标签: sql sql-server


【解决方案1】:

您可以使用CROSS APPLYVALUES 子句来执行此操作。使用VALUES 对所有比较的列进行分组,然后选择最大值。

SELECT 
        MAX(d.data1) as MaxOfColumns
        ,MIN(d.data1) as MinOfColumns
        ,a.id
        ,a.name
  FROM YOURTABLE as a 
  CROSS APPLY   (    
                VALUES(a.col_to_compare1)
                     ,(a.col_to_compare2)
                     ,(a. col_to_compare3)
                     ,(a.col_to_compare4)
                     ,(a. col_to_compare5)
                ) as d(data1) --Name the Column
   GROUP BY a.id
            ,a.name

【讨论】:

    【解决方案2】:

    假设您正在寻找每行的最小值/最大值

    Declare @YourTable table (id int,name varchar(50),col_to_compare1 int,col_to_compare2 int,col_to_compare3 int,col_to_compare4 int)
    Insert Into @YourTable values
    (1,'John',5,5,2,1),
    (2,'Peter',3,2,4,1),
    (3,'Josh',3,5,1,3)
    
    Select A.ID
          ,A.Name
          ,MinVal = min(B.N)
          ,MaxVal = max(B.N)
     From  @YourTable A
     Cross Apply (Select N From (values(a.col_to_compare1),(a.col_to_compare2),(a.col_to_compare3),(a.col_to_compare4)) N(N) ) B
     Group By A.ID,A.Name
    

    返回

    ID  Name    MinVal  MaxVal
    1   John    1       5
    3   Josh    1       5
    2   Peter   1       4
    

    【讨论】:

      【解决方案3】:

      这些解决方案保留当前行并添加额外的最小/最大列。

      select      *
      
      from        t cross apply   
      
                 (select  min(col)   as min_col
                         ,max(col)   as max_col
      
                  from    (
                              values
      
                              (t.col_to_compare1)
                             ,(t.col_to_compare2)
                             ,(t.col_to_compare3)    
                             ,(t.col_to_compare4)
      
                          ) c(col)
                  ) c 
      

      select      *
                 ,cast ('' as xml).value ('min ((sql:column("t.col_to_compare1"),sql:column("t.col_to_compare2"),sql:column("t.col_to_compare3"),sql:column("t.col_to_compare4")))','int')    as min_col
                 ,cast ('' as xml).value ('max ((sql:column("t.col_to_compare1"),sql:column("t.col_to_compare2"),sql:column("t.col_to_compare3"),sql:column("t.col_to_compare4")))','int')    as max_col
      
      from        t   
      

      +----+-------+-----------------+-----------------+-----------------+-----------------+---------+---------+
      | id | name  | col_to_compare1 | col_to_compare2 | col_to_compare3 | col_to_compare4 | min_col | max_col |
      +----+-------+-----------------+-----------------+-----------------+-----------------+---------+---------+
      | 1  | John  | 5               | 5               | 2               | 1               | 1       | 5       |
      +----+-------+-----------------+-----------------+-----------------+-----------------+---------+---------+
      | 2  | Peter | 3               | 2               | 4               | 1               | 1       | 4       |
      +----+-------+-----------------+-----------------+-----------------+-----------------+---------+---------+
      | 3  | Josh  | 3               | 5               | 1               | 3               | 1       | 5       |
      +----+-------+-----------------+-----------------+-----------------+-----------------+---------+---------+
      

      【讨论】:

      • 这太完美了!非常感谢!
      【解决方案4】:

      一种方法是“分解”数据

      declare @table table (id int, name varchar(10), col1 int, col2 int, col3 int, col4 int)
      
      insert into @table values (1 , 'John' , 5 , 5 , 2 , 1)
      insert into @table values (2 , 'Peter' , 3 , 2 , 4 , 1)
      insert into @table values (3 , 'Josh' , 3 , 5 , 1 , 3)
      
      
      ;with stretch as
      (
          select id, col1 as col from @table
          union all
          select id, col2 as col from @table
          union all
          select id, col3 as col from @table
          union all
          select id, col4 as col from @table
      )
      
      select
          t.id, 
          t.name, 
          agg.MinCol, 
          agg.MaxCol
      from @table t
          inner join 
          (
              select
                  id, min(col) as MinCol, max(col) as MaxCol
              from stretch
              group by id
          ) agg
              on t.id = agg.id
      

      【讨论】:

        【解决方案5】:

        看起来很简单

        SELECT min(col1), max(col1), min(col2), max(col2), min(col3), max(col3), min(col4), max(col4) FROM table
        

        为您提供每列的最小值和最大值。

        根据 OP 的评论,我相信他可能正在寻找按被查询人分组的最小值/最大值。

        那就是:

        SELECT name, min(col1), max(col1), min(col2), max(col2), min(col3), max(col3), min(col4), max(col4) FROM table GROUP BY name
        

        【讨论】:

        • 是的,列,但我需要行中的值。嘟嘟上面的解决方案就完美了。
        猜你喜欢
        • 2021-09-23
        • 2015-03-24
        • 2016-05-02
        • 2013-10-06
        • 2020-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多