简体   繁体   中英

Select rows from a SQL Server Database table only rows that have another column as the maximum

I'm trying to select rows from a Microsoft SQL Server Database table that for each ID in one column (ID) select only rows that have another column as the maximum (IDtoBeMaxed). For example:

From this table

  ID  SomeValue IDtoBeMaxed
  1   56        2  
  1   59        2  
  1   80        1
  2   55        5
  2   80        5
  2   56        3
  2   81        3

I only want

  ID  SomeValue IDtoBeMaxed
  1   56        2  
  1   59        2  
  2   55        5
  2   80        5

I have this query which works, but I think there should be a faster way that reduces the response time of the query. So again, this query gives me what I want, I am looking for a faster response time query.

SELECT * 
FROM myTable 
WHERE ID = 2 
  AND IDtoBeMaxed = (SELECT MAX(IDtoBeMaxed) FROM myTable WHERE ID = 2)

Edits: I don't need all the rows, like I showed in the example above. I only need rows for a specific ID, just like the query that I wrote myself.

Results: I tried Shavkat query but it's not any faster than the query I had written. The rest of the answers return all the rows which I am not looking for. So this is still up for debate. But thanks for your answers so far.

Are you trying to return all rows from the table in one query? Something like the following would work:

SELECT t.Id,t.SomeValue,t.IDtoBeMaxed
FROM MyTable t
JOIN (
    SELECT Id,MAX(IDToBeMaxed) AS MaxId
    FROM MyTable
    GROUP BY Id
) AS m ON t.Id=m.Id AND t.IDToBeMaxed=m.MaxId

In response to your edits:

The query you've written is about as simple as you can get. If you need to improve response time you should look at creating an index on the ID and IDToBeMaxed columns.

CREATE INDEX ix_IDMaxed ON MyTable(ID,IDToBeMaxed)

Is that an option for you?

Here is an old-school one:

declare @myTable table (ID int,  SomeValue int, IDtoBeMaxed int)
insert into @myTable
values
  (1,   56,        2 ), 
  (1,   59,        2 ),  
  (1,   80,        1 ),
  (2,   55,        5 ),
  (2,   80,        5 ),
  (2,   56,        3 ),
  (2,   81,        3 ),
  (3,   55,        5 ),
  (3,   80,        5 ),
  (3,   56,        5 ),
  (3,   81,        5 )

select a.*
from @myTable a left join @myTable b 
on a.ID = b.ID and a.IDtoBeMaxed < b.IDtoBeMaxed
where b.ID is null and a.ID = 2

Could you please try below...

WITH    selectOne
          AS ( SELECT   ROW_NUMBER() OVER ( PARTITION BY SomeValue, ID ORDER BY IDtoBeMaxed DESC ) AS RowNum ,
                        ID ,
                        SomeValue ,
                        IDtoBeMaxed
               FROM     myTable
             )
    SELECT  *
    FROM    selectOne
    WHERE   RowNum = 1

The following example return the records ranked by their IDtoBeMaxed

;WITH cte AS
 (SELECT *, DENSE_RANK() OVER(PARTITION BY ID ORDER BY IDtoBeMaxed DESC) AS dr
  FROM myTable
  )
  SELECT *
  FROM cte
  WHERE dr = 1

Demo on SQLFiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM