【问题标题】:Oracle Group By IssueOracle 按问题分组
【发布时间】:2010-12-31 00:34:48
【问题描述】:

我正在努力解决似乎很容易解决的问题(至少对我来说是在 MySQL / SqlServer 中!)

我会简化问题。假设我有下表:

表投票

ID  ID_IDEA DATE_VOTE   with ID_IDEA FK(IDEA.ID)
1   3       10/10/10
2   0       09/09/10
3   3       08/08/10
4   3       11/11/10
5   0       06/06/10
6   1       05/05/10

我正在尝试查找每个想法的最新投票,这意味着我只想返回 ID 为 4、2 和 6 的行。

在 Oracle 看来,如果不使用 SUM()、AVG 等函数,您就无法使用 GROUP BY。我对它应该如何工作感到有些困惑。

请指教,

谢谢。

【问题讨论】:

    标签: sql oracle group-by


    【解决方案1】:
    SELECT id,
           id_idea,
           date_vote
    FROM   (SELECT id,
                   id_idea,
                   date_vote,
                   Row_number() over (PARTITION BY id_idea 
                                          ORDER BY date_vote DESC NULLS LAST) AS rn
            FROM   VOTE) AS t
    WHERE  rn = 1  
    

    【讨论】:

    • 通常在 ORDERing DESC 时,强制 NULL 为 LAST 是个好主意,这样您更有可能选择包含真实数据的行。
    【解决方案2】:

    据我了解,您正在寻找这个:

    选择 id_idea,最大值(日期投票) 从投票 按 id_idea 分组

    编辑:如果您需要获得完整的行,请重新考虑:

    选择 v.* 从投票 v JOIN (SELECT id_idea, max(date_vote) as max_date 从投票 按 id_idea 分组)t ON t.id_idea = v.id_idea AND t.max_date = v.date_vote

    【讨论】:

    • 我想他们也想要id。每组查询的最大 n 个。
    • 使用第一个还是第二个查询?您是否对我的查询进行了任何更改?
    • 是的,我必须更改它以适应我更复杂的上下文。但是内部查询在侧面运行时不会接受分组
    • 您需要显示修改后的查询,否则我们将无法说出错误的原因。 “边跑”是什么意思?
    【解决方案3】:

    如果您可以通过简单的聚合来处理此类查询,则不应使用分析函数来处理:

    SQL> create table vote(id,id_idea,date_vote)
      2  as
      3  select 1, 3, date '2010-10-10' from dual union all
      4  select 2, 0, date '2010-09-09' from dual union all
      5  select 3, 3, date '2010-08-08' from dual union all
      6  select 4, 3, date '2010-11-11' from dual union all
      7  select 5, 0, date '2010-06-06' from dual union all
      8  select 6, 1, date '2010-05-05' from dual
      9  /
    
    Table created.
    
    SQL> select max(id) keep (dense_rank last order by date_vote) id
      2       , id_idea
      3       , max(date_vote) date_vote
      4    from vote
      5   group by id_idea
      6  /
    
            ID    ID_IDEA DATE_VOTE
    ---------- ---------- -------------------
             2          0 09-09-2010 00:00:00
             6          1 05-05-2010 00:00:00
             4          3 11-11-2010 00:00:00
    
    3 rows selected.
    

    与解析变体相比:

    1) 它可以工作(好吧,如果你在 'AS t' 中删除 'AS',解析也可以工作)

    2) 更短

    3) 更清晰(好吧,这是主观的)

    4) 它的性能稍微好一点,请参阅:

    这是聚合查询的计划:

    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2103353780
    
    ---------------------------------------------------------------------------
    | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |     3 |    39 |     4  (25)| 00:00:01 |
    |   1 |  SORT GROUP BY     |      |     3 |    39 |     4  (25)| 00:00:01 |
    |   2 |   TABLE ACCESS FULL| VOTE |     6 |    78 |     3   (0)| 00:00:01 |
    ---------------------------------------------------------------------------
    

    这是分析查询的计划:

    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 781916126
    
    ---------------------------------------------------------------------------------
    | Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT         |      |     6 |   288 |     4  (25)| 00:00:01 |
    |*  1 |  VIEW                    |      |     6 |   288 |     4  (25)| 00:00:01 |
    |*  2 |   WINDOW SORT PUSHED RANK|      |     6 |    78 |     4  (25)| 00:00:01 |
    |   3 |    TABLE ACCESS FULL     | VOTE |     6 |    78 |     3   (0)| 00:00:01 |
    ---------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("RN"=1)
       2 - filter(ROW_NUMBER() OVER ( PARTITION BY "ID_IDEA" ORDER BY
                  INTERNAL_FUNCTION("DATE_VOTE") DESC  NULLS LAST)<=1)
    

    问候, 抢。

    【讨论】:

    • 感谢您的深入回答 Rob。在阅读您的答案之前,我们实际上最终做了类似的事情。
    【解决方案4】:

    我通常会使用first or last function 来执行此操作。它有一点奇怪的结构,这可以解释为什么它不经常被使用。请注意,只要 order by 子句是确定性的,那么 max/min 并不重要(但这是必需的,因为这是构造函数的方式。

    select 
      max(id) keep (dense_rank last order by date_vote) as id,
      id_idea,
      max(date_vote)
      from vote
    group by id_idea
    

    【讨论】:

      猜你喜欢
      • 2020-12-05
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-30
      • 2011-04-01
      • 2021-10-27
      • 2014-05-24
      相关资源
      最近更新 更多