【问题标题】:Retrieving either indexed data or the last record in each group检索索引数据或每组中的最后一条记录
【发布时间】:2020-07-19 10:07:42
【问题描述】:

有一个表routes包含如下数据:

Id   GroupID   TickID   Data
-------------------------
1    1         1        A
2    1         2        B
3    1         3        C
4    2         1        D
5    2         2        E
6    3         1        F

我有一个 PHP 文件,用户应该能够在其中传递一个“TickID”,并且脚本应该返回:对于每个 GroupID,用户给定 TickID 的数据,但是如果用户传递一个 TickID,它是大于某个 GroupID 中的最大 TickID,应返回该特定 GroupID 的最后一行。

UserInput,TickID 1,返回

Id   GroupID   TickID   Data
-------------------------
1    1         1        A
4    2         1        D
6    3         1        F

UserInput,TickID 3,返回

Id   GroupID   TickID   Data
-------------------------
3    1         3        C
5    2         2        E
6    3         1        F

我找到了如何选择“最新”行,即每个 GroupID 的最大 TickID 已经在这里:Retrieving the last record in each group - MySQL

但我不知道如何将它与中间的一系列行结合起来。

编辑 我现在拥有的是: 进行 3 次查询:

第一个查询:为每个组选择最大的 TickID SELECT GroupID, MAX(TickID) maxTick From routes GROUP BY GroupID

比做两个查询: 一个用于在数据库中确实具有大于用户输入的 TickID 条目的 GroupsID -> SELECT GroupID, Data From routes WHERE TickID = userTickID GROUP BY GroupID

对没有用户给定的 TickID 的组执行另一个查询:为这些组选择最大的 TickID。 类似于Retrieving the last record in each group - MySQL

似乎是一个很大的不良行为。 有什么改进的办法吗?

【问题讨论】:

    标签: mysql


    【解决方案1】:

    我会将您的查询表述为:

    SELECT r1.*
    FROM routes r1
    INNER JOIN
    (
        SELECT GroupID, MAX(TickID) AS MaxTickID
        FROM routes
        GROUP BY GroupID
    ) r2
        ON r1.GroupID = r2.GroupID AND
           (r1.TickID = userTickID OR
            (r1.TickID = r2.MaxTickID AND r2.MaxTickID < userTickID));
    

    这里的逻辑是对每组加入方法的规范最大数量的轻微影响。这里我们采用TickID,只有当用户勾选 ID 大于 时,它才是组中的最大值。否则,我们取TickID 与输入用户值匹配的记录。

    routes 上添加以下索引应该会显着加快最大子查询:

    CREATE INDEX idx ON routes (GroupID, TickID);
    

    【讨论】:

    • 谢谢,我去看看。 t1 在查询的最后两行应该是r1 我想:) 和t2 同样:) 但它似乎工作。如何使它最大。高性能?在表上添加索引(GroupID、TickID)?
    • @tim 检查更新的答案。顺便说一句,伟大的名字让我想起了自己:-P
    • 谢谢,是的,我有这个索引。而且速度很棒。很好的查询,非常感谢!
    【解决方案2】:

    我认为这取决于数据。

    • (A) TickID 的 id 是否总是连续的?例如TickID=1,2,3,4,5,6
    • (B) 在某些情况下可以跳过数字吗?例如TickID=1,4​​,6

    (A)查询如下。

    select * from routes
      where (GroupID, TickID) in
        (select GroupID, max(TickID) from routes where TickID<=3 group by GroupID);
    

    (B)查询如下。

    with
    MatchUserInput as (
      select GroupID, TickID from routes where TickID=3
    ),
    MaxTickID as (
      select GroupID, max(TickID) from routes
        where GroupID not in (select GroupID from MatchUserInput) group by GroupID
    )
    select * from routes
    where (GroupID, TickID) in (
      select * from MatchUserInput
      union select * from MaxTickID
    );
    

    将上面的“3”替换为 UserInput。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-21
      相关资源
      最近更新 更多