如何编写sql查询以选择一列中具有最大值的行

Posted

技术标签:

【中文标题】如何编写sql查询以选择一列中具有最大值的行【英文标题】:how to write sql query to select rows with max value in one column 【发布时间】:2017-06-28 02:53:10 【问题描述】:

我的桌子是这样的。

Id   |  Name  |  Ref  | Date        | From
10   |  Ant   |  100  | 2017-02-02  | David
10   |  Ant   |  300  | 2016-01-01  | David
2    |  Cat   |  90   | 2017-09-09  | David
2    |  Cat   |  500  | 2016-02-03  | David
3    |  Bird  |  150  | 2017-06-28  | David

这就是我想要的结果。

Id   |  Name  |  Ref  | Date       | From
3    |  Bird  |  150  | 2017-06-28 | David
2    |  Cat   |  500  | 2016-02-03 | David
10   |  Ant   |  300  | 2016-01-01 | David

我的目标是每个 ID 的最高 Ref,按 Order Date desc 排序。

能否请您告诉我如何使用 pl/sql 编写 sql 查询。

【问题讨论】:

每次你被要求解决一个关于“最高”或“最低”的问题时,你必须考虑重复(并列)。如果 Ant 的两行 Ref = 300 会怎样?两者哪个“最高”?您需要在结果中包含两行吗?还是只取最近日期的那个?或者在 Ref 列中不可能重复?然后,当您按日期排序结果时 - 如果两个日期相等,您如何打破平局? 【参考方案1】:

这种要求(您需要一列的最大值或最小值,按另一列分组,但您需要最大值或最小值行中的所有数据)几乎就是 分析函数为了。我使用了row_number - 如果可能有联系,您需要澄清分配(请参阅我在您的问题下的评论),并且根据细节,另一个分析功能可能更合适 - 也许rank()

with
     my_table ( id, name, ref, dt, frm ) as (
       select 10, 'Ant' , 100, date '2017-02-02', 'David' from dual union all
       select 10, 'Ant' , 300, date '2016-01-01', 'David' from dual union all
       select  2, 'Cat' ,  90, date '2017-09-09', 'David' from dual union all
       select  2, 'Cat' , 500, date '2016-02-03', 'David' from dual union all
       select  3, 'Bird', 150, date '2017-06-28', 'David' from dual
     )
-- End of simulated table (for testing purposes only, not part of the solution).
-- SQL query begins BELOW THIS LINE.
select   id, name, ref, dt, frm
from     (
           select id, name, ref, dt, frm,
                  row_number() over (partition by id order by ref desc, dt desc) as rn
           from   my_table
         )
where    rn = 1
order by dt desc
;

ID  NAME  REF  DT          FRM 
--  ----  ---  ----------  -----
 3  Bird  150  2017-06-28  David
 2  Cat   500  2016-02-03  David
10  Ant   300  2016-01-01  David

【讨论】:

【参考方案2】:

你可以用这个

SELECT
Id
,Name
,Ref
,[Date]
FROM(
SELECT 
* 
, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Ref DESC) AS Row#
FROM yourtable
) A WHERE Row# = 1
ORDER BY A.[Date] DESC

【讨论】:

【参考方案3】:

另一种自加入的解决方案(想法来自这里:How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?):

with
    my_table ( id, name, ref, dt, frm ) as (
      select 10, 'Ant' , 100, date '2017-02-02', 'David' from dual union all
      select 10, 'Ant' , 300, date '2016-01-01', 'David' from dual union all
      select 10, 'Ant' , 300, date '2015-01-01', 'David' from dual union all
      select  2, 'Cat' ,  90, date '2017-09-09', 'David' from dual union all
      select  2, 'Cat' , 500, date '2016-02-03', 'David' from dual union all
      select  3, 'Bird', 150, date '2017-06-28', 'David' from dual
    )
-- End of simulated table (for testing purposes only, not part of the solution).
-- SQL query begins BELOW THIS LINE.

select m1.* 
from my_table m1 
left join my_table m2 
on m1.id = m2.id and (
 -- this is basically a comparator: order by ref desc, dt desc
 m1.ref < m2.ref or (
   m1.ref = m2.ref and 
   m1.dt < m2.dt
 )
) where m2.id is null order by m1.dt desc
;

        ID NAME        REF DT        FRM 
---------- ---- ---------- --------- -----
         3 Bird        150 28-JUN-17 David
         2 Cat         500 03-FEB-16 David
        10 Ant         300 01-JAN-16 David

【讨论】:

【参考方案4】:

使用“优于”SQL 主体:

select a.Id, a.Name, a.Ref, a.Dt, a.frm
from table_name a
left join table_name b on a.id = b.id and b.ref > a.ref -- b.ref > a.ref would make b.ref "better" that a
where b.id is null -- Now check and make sure there is nothing "better"
group by a.id;

【讨论】:

【参考方案5】:
SELECT Id, Name, Max(Ref) as Ref, Min(`Date`) as `Date`
From Forge
Group By Id, Name
Order by Min(`Date`) desc;

【讨论】:

这看起来不像 Oracle - Oracle 中没有反引号。修复此问题后,查询将从一行中选择 max(ref) 并从另一行中选择 min(date) - 这不是 OP 想要的。

以上是关于如何编写sql查询以选择一列中具有最大值的行的主要内容,如果未能解决你的问题,请参考以下文章

如何获取熊猫数据框中的行,列中具有最大值并保留原始索引?

如何查询仅出现特定列中具有最高值的行的行?

SQL根据一列中的最大值从多列中选择不同的行

SQL:根据另一列的值在列上保留一个具有最大值的行

如何编写 SQL 来选择具有每个组的最大值(值)的行?

如何编写 SQL 查询以获取具有相同前缀的行