【问题标题】:Row-wise maximum in T-SQL [duplicate]T-SQL中的逐行最大值[重复]
【发布时间】:2015-06-23 12:30:46
【问题描述】:

我有一个包含几列的表格,对于每一行我想要最大值:

-- Table:
+----+----+----+----+----+
| ID | C1 | C2 | C3 | C4 |
+----+----+----+----+----+
|  1 |  1 |  2 |  3 |  4 |
|  2 | 11 | 10 | 11 |  9 |
|  3 |  3 |  1 |  4 |  1 |
|  4 |  0 |  2 |  1 |  0 |
|  5 |  2 |  7 |  1 |  8 |
+----+----+----+----+----+


-- Desired result:
+----+---------+
| ID | row_max |
+----+---------+
|  1 |       4 |
|  2 |      11 |
|  3 |       4 |
|  4 |       2 |
|  5 |       8 |
+----+---------+

如果有两到三列,我会写在iifCASE 语句中。

select ID
  , iif(C1 > C2, C1, C2) row_max
from table

但是随着列的增多,这很快就会变得很麻烦。有没有一种很好的方法来获得这个逐行最大值?在 R 中,这被称为“并行最大值”,所以我喜欢类似

select ID
  , pmax(C1, C2, C3, C4) row_max
from table

【问题讨论】:

标签: sql tsql unpivot


【解决方案1】:

如何取消透视数据以获得结果?你说的是 tsql 但不是什么版本的 SQL Server。在 SQL Server 2005+ 中,您可以使用 CROSS APPLY 将列转换为行,然后获取每行的最大值:

select id, row_max = max(val)
from yourtable
cross apply
(
  select c1 union all
  select c2 union all
  select c3 union all
  select c4
) c (val)
group by id

SQL Fiddle with Demo。请注意,这可以使用 table value constructor 缩写。

这也可以通过 SQL Server 中的UNPIVOT 函数来完成:

select id, row_max = max(val)
from yourtable
unpivot
(
  val
  for col in (C1, C2, C3, C4)
) piv
group by id

SQL Fiddle with Demo。两个版本都给出了结果:

| id | row_max |
|----|---------|
|  1 |       4 |
|  2 |      11 |
|  3 |       4 |
|  4 |       2 |
|  5 |       8 |

【讨论】:

  • 交叉应用比枢轴应用更整洁吗?
  • @FabianBigler Pivot 将数据行转换为列,这正好相反。它采用多列并将其转换为行以获得最大值。
  • 我认为你也可以使用 unpivot 而不是交叉应用
  • @FabianBigler 我刚刚在我的答案中包含了一个非透视版本。
  • 好的,谢谢。但是我应该使用哪一个?
【解决方案2】:

您可以使用以下查询:

SELECT id, (SELECT MAX(c) 
            FROM (
                SELECT c = C1
                UNION ALL
                SELECT c = C2
                UNION ALL
                SELECT c = C3
                UNION ALL
                SELECT c = C4
            ) as x(c)) maxC
FROM mytable

SQL Fiddle Demo

【讨论】:

    【解决方案3】:

    一种方法使用cross apply

    select t.id, m.maxval
    from table t cross apply
         (select max(val) as maxval
          from (values (c1), (c2), (c3), (c4)) v(val)
         ) m
    

    【讨论】:

    • 为什么投反对票?这和 Giorgos 的答案是迄今为止最好的。
    • 不是我的投票,但为什么呢?想详细说明为什么这个和 Giorgos 是迄今为止最好的?
    • @bluefeet 。 . .您的答案需要汇总整个数据集。相关子查询和cross apply 只需要在少量数据内进行聚合。
    • @bluefeet 的回答实际上有两个建议,其中第一个与您的相同,只是使用的语法略有不同。无论如何,为什么你认为一次对整个集合的聚合比对一个小集合的多次聚合更糟糕?
    • @AndriyM 。 . .当我写评论时,bluefeet 没有两个答案。要点是通用聚合算法在内存和处理方面都不会扩展 O(n),因此将行数增加一倍需要两倍以上的努力。在单行上操作应该具有额外的性能优势,因为数据在聚合时是本地化的。因为这种类型的查询是一种特殊情况,所以可能有某种我不知道的专门针对这种情况的优化。
    猜你喜欢
    • 2020-03-31
    • 2012-01-02
    • 2021-12-21
    • 2015-09-10
    • 2018-02-09
    • 2012-01-28
    • 2021-07-25
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多