简体   繁体   English

SQL 查询到 select 具有最小值的不同行

[英]SQL query to select distinct row with minimum value

I want an SQL statement to get the row with a minimum value.我想要一个 SQL 语句来获取具有最小值的行。

Consider this table:考虑这张表:

id  game   point
1    x      5
1    z      4
2    y      6
3    x      2
3    y      5
3    z      8

How do I select the ids that have the minimum value in the point column, grouped by game?我如何 select 在point列中具有最小值的 ID,按游戏分组? Like the following:像下面这样:

id  game   point    
1    z      4
2    y      5
3    x      2   

Use:采用:

SELECT tbl.*
FROM TableName tbl
  INNER JOIN
  (
    SELECT Id, MIN(Point) MinPoint
    FROM TableName
    GROUP BY Id
  ) tbl1
  ON tbl1.id = tbl.id
WHERE tbl1.MinPoint = tbl.Point

This is another way of doing the same thing, which would allow you to do interesting things like select the top 5 winning games, etc.这是做同样事情的另一种方式,它可以让你做一些有趣的事情,比如选择前 5 名获胜游戏等。

 SELECT *
 FROM
 (
     SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Point) as RowNum, *
     FROM Table
 ) X 
 WHERE RowNum = 1

You can now correctly get the actual row that was identified as the one with the lowest score and you can modify the ordering function to use multiple criteria, such as "Show me the earliest game which had the smallest score", etc.您现在可以正确获取被识别为最低分数的实际行,并且您可以修改排序函数以使用多个条件,例如“显示具有最低分数的最早游戏”等。

This will work这将工作

select * from table 
where (id,point) IN (select id,min(point) from table group by id);

As this is tagged with sql only, the following is using ANSI SQL and a window function :由于仅使用sql标记,因此以下使用 ANSI SQL 和窗口函数

select id, game, point
from (
  select id, game, point, 
         row_number() over (partition by game order by point) as rn
  from games
) t
where rn = 1;

Ken Clark's answer didn't work in my case.肯克拉克的回答在我的情况下不起作用。 It might not work in yours either.它可能也不适用于您的。 If not, try this:如果没有,试试这个:

SELECT * 
from table T

INNER JOIN
  (
  select id, MIN(point) MinPoint
  from table T
  group by AccountId
  ) NewT on T.id = NewT.id and T.point = NewT.MinPoint

ORDER BY game desc
SELECT DISTINCT 
FIRST_VALUE(ID) OVER (Partition by Game ORDER BY Point) AS ID,
Game,
FIRST_VALUE(Point) OVER (Partition by Game ORDER BY Point) AS Point
FROM #T
SELECT * from room
INNER JOIN
  (
  select DISTINCT hotelNo, MIN(price) MinPrice
  from room
 Group by hotelNo
  ) NewT   
 on room.hotelNo = NewT.hotelNo and room.price = NewT.MinPrice;

This alternative approach uses SQL Server's OUTER APPLY clause.这种替代方法使用 SQL Server 的OUTER APPLY子句。 This way, it这样,它

  1. creates the distinct list of games, and创建不同的游戏列表,以及
  2. fetches and outputs the record with the lowest point number for that game.获取并输出该游戏具有最低点数的记录。

The OUTER APPLY clause can be imagined as a LEFT JOIN , but with the advantage that you can use values of the main query as parameters in the subquery (here: game). OUTER APPLY子句可以被想象成一个LEFT JOIN ,但它的优点是你可以使用主查询的值作为子查询中的参数(这里是:游戏)。

SELECT colMinPointID
FROM (
  SELECT game
  FROM table
  GROUP BY game
) As rstOuter
OUTER APPLY (
  SELECT TOP 1 id As colMinPointID
  FROM table As rstInner
  WHERE rstInner.game = rstOuter.game
  ORDER BY points
) AS rstMinPoints

This is portable - at least between ORACLE and PostgreSQL:这是可移植的——至少在 ORACLE 和 PostgreSQL 之间:

select t.* from table t 
where not exists(select 1 from table ti where ti.attr > t.attr);

Most of the answers use an inner query.大多数答案使用内部查询。 I am wondering why the following isn't suggested.我想知道为什么不建议以下内容。

select
   *
from
   table
order by
   point
fetch next 1 row only   // ... or the appropriate syntax for the particular DB

This query is very simple to write with JPAQueryFactory (a Java Query DSL class).使用JPAQueryFactory (一个 Java 查询 DSL 类)编写这个查询非常简单。

return new JPAQueryFactory(manager).
   selectFrom(QTable.table).
   setLockMode(LockModeType.OPTIMISTIC).
   orderBy(QTable.table.point.asc()).
   fetchFirst();

Try:尝试:

select id, game, min(point) from t
group by id 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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