免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: col.g
打印 上一主题 下一主题

请教min(),max()等与group by一起的情况 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2008-02-28 17:25 |只看该作者
数据量大的时候感觉用临时表会效果好一些

论坛徽章:
0
12 [报告]
发表于 2008-02-28 22:43 |只看该作者
用一个INNER JOIN实现,每次只找当前值和最大值及对应的日期,或者只找出当前值和最小值及对应的日期

类似于三楼的解决方法

要达到四楼的效果查询太复杂了,起码目前对我是这样。因此一步一步来吧,分步查询能达到效果,性能也能接受(200多万条记录,每次查询大概在一分钟左右的时候,还可以)

从CSDN的一个回复里学来

我也是感觉可能临时表可能性能方面会好一点

对了,主索引是work-id 和work-date组合

select t.work-id,t.work-date,t.prod-num,ma.max_pp,ttt.cur-prod-num,ma.max_pp/ttt.cur-prod-num
from ((select * from table-name where table-name.work-date>'2008-1-1') t inner join
      (select work-id,max(prod-num) as max_pp from table-name where table-name.work-date>'2008-1-1' group by 1 ) ma
          on t.work-id=ma.work-id and t.prod-num=ma.max_pp)
                        inner join
                        (select work-id, prod-num as cur-prod-num from table-name where work-date='2008-2-27') ttt
                                        on t.work-id=ttt.work-id
                                        order by 6

[ 本帖最后由 col.g 于 2008-2-28 22:45 编辑 ]

论坛徽章:
0
13 [报告]
发表于 2008-02-29 10:02 |只看该作者
不至于要写得这么复杂吧,有时候换个角度很容易就解决了:

SELECT a.work_id, a.prod_dat AS min_prod_dat, c.min_prod_num, b.prod_dat AS max_prod_dat, c.max_prod_num
FROM (
    SELECT work_id, min( prod_num ) AS min_prod_num, max( prod_num ) AS max_prod_num
    FROM table_name
    GROUP BY work_id
)c
JOIN table_name a ON a.work_id = c.work_id
AND a.prod_num = c.min_prod_num
JOIN table_name b ON b.work_id = c.work_id
AND b.prod_num = c.max_prod_num

论坛徽章:
0
14 [报告]
发表于 2008-02-29 10:19 |只看该作者
原帖由 sunnyfun 于 2008-2-29 10:02 发表
不至于要写得这么复杂吧,有时候换个角度很容易就解决了:

SELECT a.work_id, a.prod_dat AS min_prod_dat, c.min_prod_num, b.prod_dat AS max_prod_dat, c.max_prod_num
FROM (
    SELECT work_id, min ...



sunnyfun兄弟的SQL语句很猛。

论坛徽章:
0
15 [报告]
发表于 2008-02-29 10:19 |只看该作者
原帖由 col.g 于 2008-2-28 22:43 发表
用一个INNER JOIN实现,每次只找当前值和最大值及对应的日期,或者只找出当前值和最小值及对应的日期

类似于三楼的解决方法

要达到四楼的效果查询太复杂了,起码目前对我是这样。因此一步一步来吧,分步查 ...



如果要优化的话就加设当的索引。

create index f_u on table_name(work_id,prod_num);
explain
select a.work_id,a.prod_date as max_date,a.prod_num as max_num,b.prod_date as min_date,b.prod_num as min_num
from (select * from table_name as a where a.prod_num = (select max(prod_num) from table_name where work_id = a.work_id
)) as a,(select * from table_name as a where a.prod_num = (select min(prod_num) from table_name where work_id = a.work_id )) as b where a.work_id = b.work_id;

explain
SELECT a.work_id, a.prod_date AS min_prod_dat, c.min_prod_num, b.prod_date AS max_prod_dat, c.max_prod_num
FROM (
    SELECT work_id, min( prod_num ) AS min_prod_num, max( prod_num ) AS max_prod_num
    FROM table_name
    GROUP BY work_id
)c
JOIN table_name a ON a.work_id = c.work_id
AND a.prod_num = c.min_prod_num
JOIN table_name b ON b.work_id = c.work_id
AND b.prod_num = c.max_prod_num

论坛徽章:
0
16 [报告]
发表于 2008-02-29 10:21 |只看该作者
看一下两个EXPLAIN的结果:

mysql> explain
    -> select a.work_id,a.prod_date as max_date,a.prod_num as max_num,b.prod_date as min_date,b.prod_num as min_num
    -> from (select * from table_name as a where a.prod_num = (select max(prod_num) from table_name where work_id = a.work_id
    -> )) as a,(select * from table_name as a where a.prod_num = (select min(prod_num) from table_name where work_id = a.work_id )) as b where a.work_id = b.work_id;
+----+--------------------+------------+------+---------------+------+---------+------------------+------+-------------+
| id | select_type        | table      | type | possible_keys | key  | key_len | ref              | rows | Extra       |
+----+--------------------+------------+------+---------------+------+---------+------------------+------+-------------+
|  1 | PRIMARY            | <derived2> | ALL  | NULL          | NULL | NULL    | NULL             |    2 |             |
|  1 | PRIMARY            | <derived4> | ALL  | NULL          | NULL | NULL    | NULL             |    2 | Using where |
|  4 | DERIVED            | a          | ALL  | NULL          | NULL | NULL    | NULL             |    7 | Using where |
|  5 | DEPENDENT SUBQUERY | table_name | ref  | f_u           | f_u  | 4       | t_girl.a.work_id |    1 | Using index |
|  2 | DERIVED            | a          | ALL  | NULL          | NULL | NULL    | NULL             |    7 | Using where |
|  3 | DEPENDENT SUBQUERY | table_name | ref  | f_u           | f_u  | 4       | t_girl.a.work_id |    1 | Using index |
+----+--------------------+------------+------+---------------+------+---------+------------------+------+-------------+
6 rows in set (0.00 sec)

mysql> explain
    -> SELECT a.work_id, a.prod_date AS min_prod_dat, c.min_prod_num, b.prod_date AS max_prod_dat, c.max_prod_num
    -> FROM (
    ->     SELECT work_id, min( prod_num ) AS min_prod_num, max( prod_num ) AS max_prod_num
    ->     FROM table_name
    ->     GROUP BY work_id
    -> )c
    -> JOIN table_name a ON a.work_id = c.work_id
    -> AND a.prod_num = c.min_prod_num
    -> JOIN table_name b ON b.work_id = c.work_id
    -> AND b.prod_num = c.max_prod_num
    -> ;
+----+-------------+------------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table      | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+------------+-------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL | NULL    | NULL |    2 |             |
|  1 | PRIMARY     | a          | ALL   | f_u           | NULL | NULL    | NULL |    6 | Using where |
|  1 | PRIMARY     | b          | ALL   | f_u           | NULL | NULL    | NULL |    6 | Using where |
|  2 | DERIVED     | table_name | index | NULL          | f_u  | 8       | NULL |    7 | Using index |
+----+-------------+------------+-------+---------------+------+---------+------+------+-------------+
4 rows in set (0.00 sec)

mysql>

论坛徽章:
0
17 [报告]
发表于 2008-02-29 11:03 |只看该作者
等我慢慢体会一下楼上两位的方法

谢谢谢谢,非常感谢!

论坛徽章:
0
18 [报告]
发表于 2008-02-29 15:10 |只看该作者
原帖由 yueliangdao0608 于 2008-2-29 10:21 发表
看一下两个EXPLAIN的结果:

mysql> explain
    -> select a.work_id,a.prod_date as max_date,a.prod_num as max_num,b.prod_date as min_date,b.prod_num as min_num
    -> from (select * from tabl ...


不公平啊
人家主索引是work-id 和work-date组合,create index 前先加上
  1. ALTER TABLE `table_name` ADD PRIMARY KEY ( `work_id` , `prod_date` ) ;
复制代码
+----+-------------+------------+-------+-----------------+---------+---------+-----------+------+-------------+
| id | select_type | table      | type  | possible_keys   | key     | key_len | ref       | rows | Extra       |
+----+-------------+------------+-------+-----------------+---------+---------+-----------+------+-------------+
|  1 | PRIMARY     | <derived2> | ALL   | NULL            | NULL    |    NULL | NULL      |    2 |             |
|  1 | PRIMARY     | a          | ref   | PRIMARY,work_id | PRIMARY |       4 | c.work_id |    1 | Using where |
|  1 | PRIMARY     | b          | ref   | PRIMARY,work_id | PRIMARY |       4 | c.work_id |    1 | Using where |
|  2 | DERIVED     | table_name | index | NULL            | work_id |       8 | NULL      |    7 | Using index |
+----+-------------+------------+-------+-----------------+---------+---------+-----------+------+-------------+
4 rows in set (0.00 sec)

论坛徽章:
0
19 [报告]
发表于 2008-03-01 09:11 |只看该作者
原帖由 sunnyfun 于 2008-2-29 15:10 发表


不公平啊
人家主索引是work-id 和work-date组合,create index 前先加上ALTER TABLE `table_name` ADD PRIMARY KEY ( `work_id` , `prod_date` ) ;



LZ没有说什么索引。

论坛徽章:
0
20 [报告]
发表于 2008-03-03 08:58 |只看该作者
原帖由 yueliangdao0608 于 2008-3-1 09:11 发表



LZ没有说什么索引。


参见12楼
对了,主索引是work-id 和work-date组合


您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP