how to write sql query to select rows with max val

2019-05-30 16:43发布

My Table looks like this.

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

This is the result I want.

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

My target is the highest Ref per Id, ordered by Order Date desc.

Could you please tell me about how to write a sql query using pl/sql.

5条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-05-30 16:58

This kind of requirement (where you need the max or min by one column, grouped by another, but you need all the data from the max or min row) is pretty much what analytic functions are for. I used row_number - if ties are possible, you need to clarify the assignment (see my Comment under your question), and depending on the details, another analytic function may be more appropriate - perhaps 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
查看更多
Luminary・发光体
3楼-- · 2019-05-30 17:01

You can use this

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
查看更多
\"骚年 ilove
4楼-- · 2019-05-30 17:09

Another solution with a self join (Idea came from here: 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
查看更多
Luminary・发光体
5楼-- · 2019-05-30 17:09
SELECT Id, Name, Max(Ref) as Ref, Min(`Date`) as `Date`
From Forge
Group By Id, Name
Order by Min(`Date`) desc;
查看更多
对你真心纯属浪费
6楼-- · 2019-05-30 17:19

Use the "better than" SQL principal:

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;
查看更多
登录 后发表回答