当前位置: 首页 > 面试题库 >

根据其他列的顺序从组中选择一个值

督冠玉
2023-03-14
问题内容

假设我有这张桌子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。换句话说,我的结果应该是

| 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)附加组件或补丁,它确实为此提供了功能。但是我也欢迎其他有用的灵感。任何没有依赖子查询的方法都可以作为答案。

如果您的解决方案仅适用于单个排序列,即无法区分cathorse,请随时提出答案,我希望它对大多数用例仍然有用。例如,100*a+b一种可能的方式是按两列对上述数据进行排序,同时仍仅使用一个表达式。

我想到了一些漂亮的解决方案,可能会在一段时间后添加它们,但是我首先要看看是否先倒入了一些不错的新解决方案。

基准结果

由于仅通过查看就很难比较各种答案,因此我对它们进行了一些基准测试。这是使用MySQL
5.1在我自己的桌面上运行的。这些数字不会与任何其他系统进行比较,而只能与其他系统进行比较。如果性能对应用程序至关重要,则您可能应该使用真实数据进行自己的测试。当出现新答案时,我可以将其添加到脚本中,然后重新运行所有测试。

  • 100,000个项目,有1,000个组可供选择,InnoDb:
    1. MvG为0.166s(来自问题)
    2. RichardTheKiwi为0.520秒
    3. xdazz 2.199s
    4. 19.24s为民主党(顺序的子查询)
    5. 攻击48.72秒
  • 100,000个项目,50,000个组可供选择,InnoDb:
    1. xdazz为0.356秒
    2. 理查德· 奇异鸟0.640秒
    3. MvG为0.764秒(来自问题)
    4. 连击51.50秒
    5. __对于 Dems 而言太长 (顺序子查询)
  • 100,000个项目,InnoDb有100组可供选择:
    1. MvG为0.163秒(来自问题)
    2. 理查德·奇异鸟(RichardTheKiwi)0.523秒
    3. 2.072s为民主党(顺序的子查询)
    4. xdazz为17.78秒
    5. 攻击49.85秒

因此,到目前为止,即使是依赖子查询,我自己的解决方案似乎也还不错。令人惊讶的是,同样使用依赖子查询的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)。



 类似资料:
  • 问题内容: 我想创建两个下拉列表,类别和项目。 如果我选择名为car的类别之一,则项目下拉列表应包含Honda,Volvo和Nissan。 如果我选择一个名为phone的类别,则项目下拉列表应具有此iPhone,Samsung,Nokia。 我怎样才能做到这一点?我知道我无法使用纯HTML做到这一点。 问题答案: 工作演示 (带有jquery) 更新 :使用eval()能够添加所需的任意数量的数组

  • 问题内容: 我有2个表,一个包含我需要的最终结果,另一个包含我需要根据设定级别选择的列列表。 例如 : 所以,如果我做以下 然后,基本上我需要使用此select语句中的列名来确定从另一条语句中选择了哪些列。 香港专业教育学院尝试过的方法,我当然知道这是错的,但可以让我对我试图做的事情有所了解。 我试图以一种动态方式构建一个sql查询,该查询可以通过我放在表中的任何列进行更改。 从理论上讲,这应与以

  • 我有一个表,它有4列()gender具有与每个客户链接的唯一值:、或。 该部门与每种产品(男性或女性)都有独特的价值 我做了一个复杂的过程。首先,使用客户信息将male和其他客户分开(创建了两个表CUST_MALEY和cust_other) 如果CUST_MALEY表中有客户,则使用join,返回men division products行(其中division='men');如果cust_oth

  • 问题内容: 具有下表(): 另一个帮助表(): 我正在寻找一个SQL查询来输出以下内容: 所以,每一次是和是 在 响应表, 汇总 对话上下文到这一点,忽略不池中的响应结束谈话的一部分。 在上面的示例中,活动 响应文本 为1中的 3 。 我尝试了以下复杂的SQL,但有时会中断将文本汇总错误的情况: 我敢肯定有更好的方法。 问题答案: 这是我的看法: 这将扫描表一次,但是我不确定它的性能是否会比您的解

  • 我有以下表在PostgreSQL 11. 我想得到具有col1,col2,col3和col4的不同值的行,如果col1,col2,col3相同,则取col1的第一个值。 期望的输出是: 我试着回答以下问题。 如何将输出限制为每col2,col3.获得一个col1值。。例如,选择col1值:3876,不包括3924。

  • 问题内容: 我在尝试制作自己的内容时遇到了麻烦,具体取决于其他方面的选择值。第一个的内容来自我的数据库中的一个表,并且运行良好,但是第二个的内容应该来自另一个表,但是我无法使其工作。这是我的,我只是在尝试证明其工作原理: 这是我的Bean部分,应该获取第二个菜单的内容: 我已经为此工作了好几个小时,但还是一无所获,我真的很着急,如果能在这里给我一些帮助,我将不胜感激。非常感谢您:D 问题答案: i