【问题标题】:get max values per group获取每组的最大值
【发布时间】:2013-01-10 15:16:59
【问题描述】:

create view "data" as select [...] 语句产生的原始数据:

projectId   resourceId  num

1052785922  318153743   10
1052785922  318153743   20
1052785922  318153743   30

1052785936  -2097765361 20
1052785936  318153743   10
1052785936  528513104   30

1052786014  -2097765361 20
1052786014  318153743   10
1052786014  528513104   30

1052786021  -2097765361 20
1052786021  318153743   10
1052786021  528513104   30

1052786099  -2097765361 20
1052786099  318153743   10

我尝试过滤以上数据以仅获取每个 projectId 具有 max(num) 的那些行。

估计结果:

projectId   resourceId  num

1052785922  318153743   30
1052785936  528513104   30
1052786014  528513104   30
1052786021  528513104   30
1052786099  -2097765361 20

我知道在 num = max(num) 上进行自我左连接的可能性,max(num) over ( partition by projectId ) 或 CTE 之类的窗口函数,但我想知道是否还有其他可能性只选择那些具有最高值的 num。

背景: 以上数据只是大图的一个点,比较复杂。由于它是一种观点,因此我不会以这种方式考虑 CTE 或任何东西。视图中提供的数据是为计划应用程序提供数据,运行时非常重要。我不想挣扎,以性能昂贵的视图选择结束。

上面的“原始数据”是一个视图结合了几十个表的数据的结果。我正在寻找一种方法来一次性过滤此视图的创建语句中的分组最大值,而无需在其间放置额外的层或视图!

【问题讨论】:

  • 如果“原始数据”是一个视图而不是一个基表,我认为没有人可以提供关于性能的最佳答案。如果没有实际的查询/视图、表的定义和索引,这只是猜测。

标签: sql sql-server sql-server-2008 tsql


【解决方案1】:

像这样:

WITH CTE
AS
(
  SELECT *,
    ROW_NUMBER() OVER(PARTITION BY projectId ORDER BY num DESC) rownum
  FROM Table1
)
SELECT projectId,   resourceId,  num
FROM CTE
WHERE rownum = 1;

SQL Fiddle Demo

这会给你:

|  PROJECTID |  RESOURCEID | NUM |
----------------------------------
| 1052785922 |   318153743 |  30 |
| 1052785936 |   528513104 |  30 |
| 1052786014 |   528513104 |  30 |
| 1052786021 |   528513104 |  30 |
| 1052786099 | -2097765361 |  20 |

【讨论】:

  • 正如 OP 中提到的,我当然知道使用 CTE 可以做到这一点。但我在过去认识到运行时问题,处理 CTE、大量数据和一堆引用视图,因为 this 之类的东西。无论如何,我会试一试..
  • 也许,我错过了确切的定义。 OP中的上述“原始数据”是一个视图组合了几十个表的数据的结果。我正在寻找一种方法来直接一次性过滤此视图的创建语句中的分组最大值,而无需在其间放置额外的层或视图。
  • @Nico 当您在同一个查询中组合这些数据时,您可以直接执行此操作,将tablename 替换为表引用(连接表、子查询等),然后执行 rownumber() 函数。还尝试显示您拥有的确切查询或表结构。
【解决方案2】:

这个巨型脚本不使用排序;)试试

SELECT *
FROM dbo.test3 t 
WHERE EXISTS (
              SELECT 1
              FROM dbo.test3                              
              WHERE projectId = t.projectId
              GROUP BY projectId
              HAVING MAX(num) = t.num
              )

SQLFiddle上的演示

【讨论】:

  • 谢谢你,但我怀疑它会起作用 - 我没有表(在你的例子中 test3 )可用于子选择,因为 OP 中的“原始数据”是视图的结果集!请参阅已编辑的 OP!可能,我没有说得那么清楚!
【解决方案3】:

我已经将视图创建为从UDF 中选择,以按照 Mahmoud 应该做的方式预处理数据。 UDF 允许我使用临时表而不是 CTE 最终可以多次执行。

感谢大家的提示!

【讨论】:

    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 2021-07-19
    • 2010-09-16
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    相关资源
    最近更新 更多