一条语句使用group by前后的变化

drop table test1;
drop table test2;

create table test1 
as
select object_id, object_name from dba_objects;
多执行几次
insert into test1 select * from test1;
select count(1) from test1;--796368

create table test2
as
select object_id, object_name from dba_objects where rownum < 100;
多执行几次 
insert into test2 select * from test2;
select count(1) from test2;--405504

然后看下面几个sql语句的执行计划和逻辑/物理读信息


SQL> alter system flush shared_pool;

System altered.

SQL> alter system flush buffer_cache;

System altered.

SQL> select * from test1 where exists (select object_id from test2 where test1.object_id=test2.object_id);

1584 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 981117694

-----------------------------------------------------------------------------
| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |       |    99 |  9108 | 14759   (1)| 00:02:58 |
|*  1 |  HASH JOIN          |       |    99 |  9108 | 14759   (1)| 00:02:58 |
|   2 |   SORT UNIQUE       |       |   371K|  4712K|   228   (4)| 00:00:03 |
|   3 |    TABLE ACCESS FULL| TEST2 |   371K|  4712K|   228   (4)| 00:00:03 |
|   4 |   TABLE ACCESS FULL | TEST1 |   441K|    33M| 12729   (1)| 00:02:33 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("TEST1"."OBJECT_ID"="TEST2"."OBJECT_ID")

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
       1181  recursive calls
          0  db block gets
      59290  consistent gets
      58886  physical reads
          0  redo size
      34450  bytes sent via SQL*Net to client
       1540  bytes received via SQL*Net from client
        107  SQL*Net roundtrips to/from client
         17  sorts (memory)
          0  sorts (disk)
       1584  rows processed
SQL> alter system flush shared_pool;

System altered.

SQL> alter system flush buffer_cache;

System altered.

SQL> select * from test1 where object_id in (select object_id from test2);

1584 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 981117694

-----------------------------------------------------------------------------
| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |       |    99 |  9108 | 14759   (1)| 00:02:58 |
|*  1 |  HASH JOIN          |       |    99 |  9108 | 14759   (1)| 00:02:58 |
|   2 |   SORT UNIQUE       |       |   371K|  4712K|   228   (4)| 00:00:03 |
|   3 |    TABLE ACCESS FULL| TEST2 |   371K|  4712K|   228   (4)| 00:00:03 |
|   4 |   TABLE ACCESS FULL | TEST1 |   441K|    33M| 12729   (1)| 00:02:33 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("OBJECT_ID"="OBJECT_ID")

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
        783  recursive calls
          0  db block gets
      59224  consistent gets
      58879  physical reads
          0  redo size
      34450  bytes sent via SQL*Net to client
       1540  bytes received via SQL*Net from client
        107  SQL*Net roundtrips to/from client
         13  sorts (memory)
          0  sorts (disk)
       1584  rows processed

SQL> select * from test1 where object_id in (select object_id from test2 group by object_id);


1584 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1692032541

---------------------------------------------------------------------------------
| Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |          |     1 |    92 | 14797   (2)| 00:02:58 |
|*  1 |  HASH JOIN           |          |     1 |    92 | 14797   (2)| 00:02:58 |
|   2 |   VIEW               | VW_NSO_1 |   371K|  4712K|   266  (17)| 00:00:04 |
|   3 |    HASH GROUP BY     |          |     1 |  4712K|   266  (17)| 00:00:04 |
|   4 |     TABLE ACCESS FULL| TEST2    |   371K|  4712K|   228   (4)| 00:00:03 |
|   5 |   TABLE ACCESS FULL  | TEST1    |   441K|    33M| 12729   (1)| 00:02:33 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("OBJECT_ID"="$nso_col_1")

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
       1207  recursive calls
          0  db block gets
      59850  consistent gets
      58886  physical reads
          0  redo size
      34450  bytes sent via SQL*Net to client
       1540  bytes received via SQL*Net from client
        107  SQL*Net roundtrips to/from client
         18  sorts (memory)
          0  sorts (disk)
       1584  rows processed

一条sql语句使用group by确实比不使用消耗更多一些,但是执行时间却比不使用甚至更短。先记录一下,有空仔细做研究。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24496749/viewspace-730076/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/24496749/viewspace-730076/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 MySQL 中,要通过 GROUP BY 子句获取最新一条记录,需要利用子查询和 ORDER BY 子句进行筛选。以下是具体步骤: 1.首先,使用子查询语句来查询每个组中最新的记录。例如:SELECT id, MAX(date) FROM table GROUP BY id 2.将该查询结果作为一个临时表,命名为 t1。 3.再次使用子查询从原表中获取每个组中符合上一步查询结果的所有记录,例如:SELECT * FROM table WHERE (id, date) IN (SELECT id, MAX(date) FROM table GROUP BY id) 4.这样就能得到每个组中最新的一条记录了。请注意,这种方法只适用于使用简单的 GROUP BY 语句的情况,如果使用复杂的 GROUP BY 语句,可能需要使用更复杂的查询方式。 总之,要通过 GROUP BY 取最新的一条记录,需要利用子查询和 ORDER BY 子句进行筛选。只有掌握了正确的查询方法,才能快速有效地查询数据库中的数据。 ### 回答2: MySQL中的GROUP BY关键字在处理一组数据时非常有用。可以使用它来对数据进行分组聚合并计算结果。然而,在实际开发中我们会遇到这样的场景:需要对一组数据进行分组,但只想取每组数据中最新的一条记录。这时候,可以通过以下方式来完成这个需求: 假设我们有一张订单表(order)包含如下字段: id、order_no、customer_id、total_price、order_time 我们要按照客户ID进行分组,并且只取每组中最新的订单记录,可以使用以下SQL语句: SELECT * FROM order o1 WHERE o1.id = ( SELECT MAX(o2.id) FROM order o2 WHERE o2.customer_id = o1.customer_id ) ORDER BY order_time DESC; 上面的查询语句会首先使用子查询获取每个客户的最新订单记录的ID,然后通过外部查询来获取完整的订单记录。 具体来说,子查询首先筛选出所有客户的订单记录,然后通过MAX()函数来得到每个客户的最新订单记录的ID。然后,外部查询使用这些最新记录的ID来获取完整的订单记录,并按照订单时间倒序排列,最新的订单排在前面。 这种方式虽然可以满足我们的需求,但是它的效率非常低下,因为每个客户的记录都需要进行一次子查询才能得到最新的订单记录。当数据量较大时,这种查询会变得非常缓慢。 针对这个问题,我们可以使用MySQL中的JOIN子句来优化这个查询,通过一次连接来获取每个客户的最新订单记录,从而提高查询效率。具体实现方式可以见下面的SQL语句: SELECT o1.* FROM order o1 INNER JOIN ( SELECT customer_id, MAX(id) as max_id FROM order GROUP BY customer_id ) o2 ON o1.customer_id = o2.customer_id AND o1.id = o2.max_id ORDER BY o1.order_time DESC; 上述SQL语句的实现原理与前面的查询类似,只是使用了JOIN字句,通过一次连接来获取每个客户的最新订单记录。在这个查询中,内部子查询根据客户ID进行分组,并通过MAX()函数获取每个客户的最新订单记录的ID和客户ID,然后JOIN操作使用这些ID来连接两张表,并取出每个客户的最新订单记录。 总之,MySQL中可以通过group by和子查询或JOIN子句来取最新的一条数据,同时需注意性能问题。 ### 回答3: MySQL中的GROUP BY语句用于将查询结果按照某一列的值进行分组。但是,有时我们需要在每个分组中取出最新的一条数据。这时,我们可以使用内联查询或LEFT JOIN语句。 1. 内联查询 内联查询是在SELECT语句中嵌套一个SELECT语句,用于在每个分组中获得最新的一条数据。具体实现方式如下: ``` SELECT t1.* FROM table_name t1 INNER JOIN ( SELECT MAX(time_column) AS max_time FROM table_name GROUP BY group_column ) t2 ON t1.time_column = t2.max_time AND t1.group_column = t2.group_column; ``` 其中,t1为原始表,t2为内联查询的结果表。首先,内联查询获取每个分组中的最新时间(MAX(time_column)),然后与原始表按时间和分组列进行JOIN操作,获取每个分组中最新的一条数据。 2. LEFT JOIN语句 LEFT JOIN语句也可以用于获取每个分组中的最新数据。具体实现方式如下: ``` SELECT t1.* FROM table_name t1 LEFT JOIN table_name t2 ON t1.group_column = t2.group_column AND t1.time_column < t2.time_column WHERE t2.time_column IS NULL; ``` 其中,t1为原始表,t2为表t1自身按照分组列分组后,时间戳小于t1时间戳的表。LEFT JOIN操作保证了t1中的每一条数据都能在t2中找到对应的数据,且包括t1中的最新一条数据。WHERE语句过滤掉t2中的数据,只留下t1中独有的最新一条数据。 无论是内联查询还是LEFT JOIN语句,都需要依赖于数据表中某一列的时间戳信息来进行结果筛选。因此,在实际应用中,需要根据需求设计合适的数据库表结构,以便进行方便且高效的数据查询。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值