MvG*_*MvG 12 mysql sql mariadb
假设我有这张桌子tab(小提琴可用).
| g | a | b | v |
---------------------
| 1 | 3 | 5 | foo |
| 1 | 4 | 7 | bar |
| 1 | 2 | 9 | baz |
| 2 | 1 | 1 | dog |
| 2 | 5 | 2 | cat |
| 2 | 5 | 3 | horse |
| 2 | 3 | 8 | pig |
Run Code Online (Sandbox Code Playgroud)
我正在按行分组g,对于每个组,我想从列中获取一个值v.但是,我不想要任何值,但我希望行中的值为maximal a,并且从所有这些中获取最大值的值b.换句话说,我的结果应该是
| 1 | bar |
| 2 | horse |
Run Code Online (Sandbox Code Playgroud)
我知道一个查询来实现这个目的:
SELECT grps.g,
(SELECT v FROM tab
WHERE g = grps.g
ORDER BY a DESC, b DESC
LIMIT 1) AS r
FROM (SELECT DISTINCT g FROM tab) grps
Run Code Online (Sandbox Code Playgroud)
但我认为这个查询相当丑陋.主要是因为它使用依赖子查询,这感觉就像一个真正的性能杀手.所以我想知道是否有一个更容易解决这个问题.
我期望这个问题的最可能的答案是MySQL(或MariaDB)的某种附加或补丁,它确实为此提供了一个功能.但我也欢迎其他有用的灵感.任何没有依赖子查询的东西都有资格作为答案.
如果您的解决方案仅适用于单个排序列,即无法区分cat和horse,请随意建议答案以及我希望它对大多数用例仍然有用.例如,100*a+b可能是两列都对上述数据进行排序的可能方式,同时仍然只使用一个表达式.
我有一些非常讨厌的解决方案,可能会在一段时间后添加它们,但我会首先看看是否有一些不错的新解决方案.
由于很难通过查看它们来比较各种答案,我已经对它们进行了一些基准测试.这是使用MySQL 5.1在我自己的桌面上运行的.这些数字不会与任何其他系统相比,只能相互比较.如果性能对您的应用程序至关重要,您可能应该使用现实数据进行自己的测试.当新答案出现时,我可能会将它们添加到我的脚本中,然后重新运行所有测试.
所以看起来到目前为止我自己的解决方案并不是那么糟糕,即使使用了从属子查询.令人惊讶的是,acatt的解决方案也使用了一个依赖子查询,因此我会考虑相同的,它的表现要差得多.可能是MySQL优化器无法应对的.RichardTheKiwi提出的解决方案似乎也具有良好的整体表现.另外两种解决方案在很大程度上取决于数据的结构.由于许多小组小组,xdazz的方法优于其他所有小组,而Dems的解决方案对于少数大型小组表现最佳(尽管仍然不是特别好).
这种方式不使用子查询.
SELECT t1.g, t1.v
FROM tab t1
LEFT JOIN tab t2 ON t1.g = t2.g AND (t1.a < t2.a OR (t1.a = t2.a AND t1.b < t2.b))
WHERE t2.g IS NULL
Run Code Online (Sandbox Code Playgroud)
说明:
LEFT JOIN的工作原理是,当t1.a处于其最大值时,没有s2.a具有更大的值,并且s2行值将为NULL.
SELECT g, a, b, v
FROM (
SELECT *,
@rn := IF(g = @g, @rn + 1, 1) rn,
@g := g
FROM (select @g := null, @rn := 0) x,
tab
ORDER BY g, a desc, b desc, v
) X
WHERE rn = 1;
Run Code Online (Sandbox Code Playgroud)
单程.所有其他解决方案看起来都是O(n ^ 2).
| 归档时间: |
|
| 查看次数: |
2333 次 |
| 最近记录: |