【问题标题】:Rewrite MySQL query without using UNION [duplicate]在不使用 UNION 的情况下重写 MySQL 查询 [重复]
【发布时间】:2014-06-06 20:12:11
【问题描述】:

我有以下查询返回正确的结果,但我确信这不是获得这些结果的最佳方式...

select * from (
    select * from features where feature_area = 0 
    order by updateStamp desc limit 1
) as feature_1

union all

select * from (
    select * from features where feature_area = 1 
    order by updateStamp desc limit 1
) as feature_2

union all

select * from (
    select * from features where feature_area = 2 
    order by updateStamp desc limit 1
) as feature_3

这会返回类似于...的结果

id    feature_area        title                  updateStamp
--------------------------------------------------------------------
103   0                   This is a title        2014-04-15 09:26:14
102   1                   Another title          2014-03-27 14:09:49
98    2                   More title             2014-01-21 16:00:55

是否可以使用联接而不是联合来改进这一点,如果可以,请您指出正确的方向。

编辑:

查看了@Ben 指出的其他选项,我似乎已经为我的特定目的获得了最快的查询(尽管不是那么吸引人)。如果您认为我错了,请随时纠正我。我不是专家,所以我在征求意见。

【问题讨论】:

  • 你能提供一个sqlfiddle
  • @Ben 这个答案表明我已经有了最好的方法??
  • 可能是@Tom,是的。只有你可以决定你是否有最好的方法。如果你所拥有的足够快,那么你不需要改变任何东西。如果速度不够快,请尝试其他选项。如果您仍然不能足够快地得到它,请回到这里提出这个问题,但包括您的索引、表 DDL 以及您尝试过的每种方法的解释计划,并且有人可能能够提供帮助。
  • 你不能只通过feature_area订购吗?
  • @Tom 下面的答案使用两个带有 group by 的 select 语句。这可以节省数据库时间,而不是执行 3 个单独的选择语句和组合结果集。如果您担心性能,您可以随时查看统计数据,看看哪个性能更好。如果您采用以下方法,索引可以进一步加快速度。

标签: mysql sql join union greatest-n-per-group


【解决方案1】:
select f.* from features f
inner join (
    select
    feature_area
    max(updateStamp) as updateStamp
    from
    features 
    where feature_are IN (0,1,2)
    group by feature_area
) sq  on sq.feature_area = f.feature_area 
and sq.updateStamp = f.updateStamp

【讨论】:

  • 感谢您...处理我目前只有 100 行的数据,使用 UNION ALL 方法稍微快一些。不过我喜欢这种方法,我从中学到了很多东西,非常感谢。
  • 这些解决方案将依赖于索引,因此在得出结论之前可能值得优化两个查询的索引。
【解决方案2】:

希望我正确阅读了您的问题。

select *
From features f
inner join ( select feature_area, max(updateStamp) as maxUpdateStamp
             from features
             Group by feature_area
            ) as minfeatures
           ON minfeatures.feature_area = f.feature_area
           AND minfeatures.maxUpdateStamp = f.updateStamp

【讨论】:

    【解决方案3】:
    with MaxFeature
    AS
    (
    select 
        feature_area        AS  feature_area        
        ,max(updateStamp)   AS  MaxUpdateStamp
    from 
        features
    group by 
        feature_area
    )
    select
        Features.*
    from
        Features
    inner join 
        Maxfeature
    on
        Features.feature_area = MaxFeature.feature_area
    and
        Features.updateStamp = MaxFeature.MaxUpdateStamp
    order by    
        Features.feature_area asc
    

    【讨论】:

    • Max updateStamp 是有道理的,但你会返回哪个idtitle
    • 好点@MarcusAdams。我忘了。但。如果 updateStamp 通常每个功能至少是唯一的(最接近的毫秒),则上述更新将起作用
    【解决方案4】:

    假设索引正确,使用反连接解决这个问题通常是最高效的:

    SELECT f1.*
    FROM features f1
    LEFT JOIN features f2
      ON f2.feature_area = f1.feature_area
      AND f2.updateStamp < f1.updateStamp
    WHERE f1.feature_area < 3
      AND f2.id IS NULL
    ORDER BY f1.feature_area
    

    如果有重复的行具有相同的feature_area和最高的updateStamp,它会返回重复的行。

    有关此技术的更多说明: Get records with highest/smallest <whatever> per group

    【讨论】:

      猜你喜欢
      • 2016-11-15
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 2012-02-25
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多