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

时间:2019-05-30 10:35:55

标签: mysql greatest-n-per-group mysql-5.7

我有一个看起来像这样的表

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

重点是在每种标题的每种语言的“值”列中选择最大值-最大值是最新值。其次,当我使用MERGE算法构建MySQL View时,想避免诸如MAX,DISTINCT或GROUP-BY之类的聚合函数,并且不想最终创建一个临时表(请参见{{3}的底部) }。

到目前为止,此方法有效,但仅返回每个标题的最大行:

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

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

3 个答案:

答案 0 :(得分:1)

此答案假定您使用的是MySQL 8+,在其中查询变得非常容易。 MySQL 8和更高版本支持分析功能,这些功能是为了解决此类问题而添加的。

我们可以在此处尝试使用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的早期版本来解决此问题,但是它需要用户变量,并且往往很丑陋。因此,如果您希望有许多与此查询类似的查询,请考虑升级。

答案 1 :(得分:1)

这应该给您您想要的东西。

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;

答案 2 :(得分:1)

您可以使用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     |