根据 MySQL 中的多列获取最大行

Get greatest rows based on multiple columns in MySQL

我有一个 table 看起来像:

id | title | value | language
---+-------+-------+---------
1  | a     | 1800  |    NULL
2  | a     | 1900  |    NULL
3  | b     | 1700  |    NULL
4  | b     | 1750  |    NULL 
5  | b     | 1790  |    1
6  | c     | 1892  |    NULL
7  | c     | 1900  |    1
8  | c     | 1910  |    2
9  | d     | 3020  |    NULL

想要得到以下结果:

id | title | value | language
---+-------+-------+---------
2  | a     | 1900  |    NULL
4  | b     | 1750  |    NULL 
5  | b     | 1790  |    1
6  | c     | 1892  |    NULL
7  | c     | 1900  |    1
8  | c     | 1910  |    2
9  | d     | 3020  |    NULL

重点是 select 每个标题的每种语言的值列中的最大值 - 最大的是最新的。其次,想避免像 MAX、DISTINCT 或 GROUP-BY 这样的聚合函数,因为我正在使用 MERGE 算法构建 MySQL 视图,并且不想最终创建一个临时的 table (参见 https://dev.mysql.com/doc/refman/5.6/en/view-algorithms.html 的底部部分)。

到目前为止这可行,但每个标题只有 returns 最大行:

SELECT t1.title
FROM table t1
LEFT OUTER JOIN table t2
  ON t1.title = t2.title
        AND t1.value < t2.value
WHERE t2.title IS NULL

如何创建一个像上面的结果那样考虑语言的结果?谢谢

此答案假设您使用的是 MySQL 8+,您的查询将变得非常容易。 MySQL8及以后版本支持解析函数,为解决此类问题而加入

我们可以在这里尝试使用 ROW_NUMBER

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY title, language ORDER BY value DESC) rn
    FROM yourTable
)

SELECT id, title, value, language
FROM cte
WHERE rn = 1;

Demo

MySQL 的早期版本有一种方法可以处理此问题,但它需要用户变量,而且往往非常丑陋。因此,如果您希望有很多与此类似的查询,可以考虑升级。

这应该能满足您的需求。

SELECT t1.title, t1.value, t1.language
FROM [Table] t1
LEFT OUTER JOIN [Table] t2 ON 
     t1.title = t2.title AND
     (IFNULL(t1.language, '') = IFNULL(t2.language, ''))
WHERE 
     t1.value > t2.value;

你可以用 NOT EXISTS:

select t.*
from tablename t
where not exists (
  select 1 from tablename
  where 
    title = t.title and 
    coalesce(language, 0) = coalesce(t.language, 0) and 
    value > t.value
)

参见demo
结果:

| id  | title | value | language |
| --- | ----- | ----- | -------- |
| 2   | a     | 1900  | NULL     |
| 4   | b     | 1750  | NULL     |
| 5   | b     | 1790  | 1        |
| 6   | c     | 1892  | NULL     |
| 7   | c     | 1900  | 1        |
| 8   | c     | 1910  | 2        |
| 9   | d     | 3020  | NULL     |