假设我有这张桌子tab(小提琴可用)。
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 |
我按行对行进行分组g,对于每个组,我都希望从column中获得一个值v。但是,我不需要 任何 值,但是我想从具有maximal的行中获取值a,并从所有这些中获取具有maximal的值b。换句话说,我的结果应该是
g
v
a
b
| 1 | bar | | 2 | horse |
我知道一个查询来实现这一点:
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
但是我认为这个查询 很难看 。主要是因为它使用了一个 依赖的子查询 ,感觉就像是真正的性能杀手。因此,我想知道是否有更简单的解决方案来解决这个问题。
我期望这个问题的最可能答案是某种MySQL(或MariaDB)附加组件或补丁,它确实为此提供了功能。但是我也欢迎其他有用的灵感。任何没有依赖子查询的方法都可以作为答案。
如果您的解决方案仅适用于单个排序列,即无法区分cat和horse,请随时提出答案,我希望它对大多数用例仍然有用。例如,100*a+b一种可能的方式是按两列对上述数据进行排序,同时仍仅使用一个表达式。
cat
horse
100*a+b
我想到了一些漂亮的解决方案,可能会在一段时间后添加它们,但是我首先要看看是否先倒入了一些不错的新解决方案。
由于仅通过查看就很难比较各种答案,因此我对它们进行了一些基准测试。这是使用MySQL 5.1在我自己的桌面上运行的。这些数字不会与任何其他系统进行比较,而只能与其他系统进行比较。如果性能对应用程序至关重要,则您可能应该使用真实数据进行自己的测试。当出现新答案时,我可以将其添加到脚本中,然后重新运行所有测试。
因此,到目前为止,即使是依赖子查询,我自己的解决方案似乎也还不错。令人惊讶的是,同样使用依赖子查询的acatt解决方案,其效果也要差得多,因此我也考虑过。MySQL优化器可能无法解决的问题。RichardTheKiwi提出的解决方案似乎也具有良好的整体性能。其他两个解决方案在很大程度上取决于数据的结构。对于许多小组,xdazz的方法要优于其他所有小组,而Dems的解决方案在少数几个小组中表现最佳(尽管仍然不是很好)。
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;
单通。在我看来,所有其他解决方案都为O(n ^ 2)。