转载

统计推荐人总数、下单金额的sql优化

表结构:

CREATE  TABLE ` p_account_log`  (

` log_id`  mediumint ( 8 )  unsigned  NOT  NULL  AUTO_INCREMENT,

` uid`  mediumint ( 8 )  unsigned  NOT  NULL  COMMENT  ' 会 员 编 号',

` use_money`  decimal ( 10, 2 )  NOT  NULL  DEFAULT  '0.00'  COMMENT  ' 可 用 资 金',

` change_time`  int ( 10 )  unsigned  NOT  NULL  COMMENT  ' 变 动 时 间',

` change_desc`  varchar ( 255 )  NOT  NULL  DEFAULT  ''  COMMENT  ' 备 注',

` change_type`  tinyint ( 3 )  unsigned  NOT  NULL  COMMENT  ' 变 动 类 型0 为 充 值 ,1 为 消 费, 2 为 充 值 会 员 3 为 推 荐 奖 励 99 为

PRIMARY  KEY  (` log_id` ),

KEY ` user_id`  (` uid` )

)  ENGINE = InnoDB  AUTO_INCREMENT = 82416  DEFAULT  CHARSET = utf8  COMMENT = ' 账 户 变 动 记 录 表';

CREATE  TABLE ` p_order`  (

` order_id`  int ( 10 )  unsigned  NOT  NULL  AUTO_INCREMENT,

` uid`  int ( 11 )  DEFAULT  '0'  COMMENT  ' 会 员 编 号',

` username`  varchar ( 30 )  DEFAULT  ''  COMMENT  ' 会 员 名',

` courier_id`  int ( 11 )  DEFAULT  '0'  COMMENT  ' 快 递ID',

` courier_name`  varchar ( 180 )  DEFAULT  ''  COMMENT  ' 快 递 名 称',

` sum_money`  decimal ( 10, 2 )  DEFAULT  '0.00'  COMMENT  ' 付 款 金 额',

` order_status`  tinyint ( 1 )  DEFAULT  '0'  COMMENT  ' 订 单 状 态',

` pay_status`  tinyint ( 1 )  DEFAULT  '0'  COMMENT  ' 付 款 状 态',

` add_time`  int ( 10 )  DEFAULT  '0'  COMMENT  ' 添 加 时 间',

` pay_time`  int ( 10 )  DEFAULT  '0'  COMMENT  ' 付 款 时 间',

` sender_name`  varchar ( 30 )  DEFAULT  ''  COMMENT  ' 发 件 人 姓 名',

` sender_province`  varchar ( 30 )  DEFAULT  ''  COMMENT  ' 发 件 人 省 份',

` sender_city`  varchar ( 30 )  DEFAULT  NULL  COMMENT  ' 发 件 人 城 市',

` sender_district`  varchar ( 30 )  DEFAULT  ''  COMMENT  ' 发 件 人 地 区',

` sender_address`  varchar ( 180 )  DEFAULT  ''  COMMENT  ' 发 件 人 详 细 地 址',

` sender_zip`  varchar ( 10 )  DEFAULT  ''  COMMENT  ' 邮 政 编 码',

` sender_mobile`  varchar ( 20 )  DEFAULT  ''  COMMENT  ' 发 件 人 手 机',

` sender_telphone`  varchar ( 20 )  DEFAULT  ''  COMMENT  ' 发 件 人 座 机',

PRIMARY  KEY  (` order_id` )

)  ENGINE = InnoDB  AUTO_INCREMENT = 63284  DEFAULT  CHARSET = utf8  COMMENT = ' 订 单 表';

CREATE  TABLE ` p_user`  (

` uid`  int ( 10 )  unsigned  NOT  NULL  AUTO_INCREMENT,

` username`  varchar ( 30 )  DEFAULT  ''  COMMENT  ' 用 户 名',

` password`  varchar ( 32 )  DEFAULT  ''  COMMENT  ' 密 码',

` mobile`  varchar ( 20 )  DEFAULT  ''  COMMENT  ' 手 机 号',

` qq`  varchar ( 20 )  DEFAULT  ''  COMMENT  'QQ',

` email`  varchar ( 160 )  DEFAULT  ''  COMMENT  ' 电 子 邮 件',

` amount`  decimal ( 10, 2 )  DEFAULT  '0.00'  COMMENT  ' 金 额',

` agent_id`  int ( 11 )  DEFAULT  '0'  COMMENT  ' 会 员 等 级ID',

` start_time`  int ( 10 )  DEFAULT  '0'  COMMENT  ' 开 始 日 期',

` wenti`  tinyint ( 2 )  DEFAULT  '0'  COMMENT  ' 问 题',

` daan`  varchar ( 100 )  DEFAULT  ''  COMMENT  ' 密 保 答 案',

` referrer_uid`  int ( 11 )  DEFAULT  '0'  COMMENT  ' 推 荐 人',

` status`  tinyint ( 1 )  DEFAULT  '1'  COMMENT  '0 禁 用 1 启 用',

` add_time`  int ( 10 )  DEFAULT  '0'  COMMENT  ' 注 册 日 期',

PRIMARY  KEY  (` uid` )

)  ENGINE = InnoDB  AUTO_INCREMENT = 4502  DEFAULT  CHARSET = utf8  COMMENT = ' 会 员 表';


数据量不是很大,会员4500, 账 户 变 动 记 录 82000,订单63000
结果:统计推荐人推荐会员总数、提成金额、推荐会员下单总金额。这里会员总数和提成金额是根据会员等级再变动,所以无法用固定比例。
第一次写的sql语句如下:

SELECT  t2. referrer_uid, t1. username, t2. count,

( SELECT  sum ( use_money )  from  p_account_log  where  change_type = 3  and  p_account_log. uid = t1. uid )  as  use_money,

( SELECT  sum ( sum_money )  from  p_order  where  uid  in  ( select  uid  from  p_user  where  referrer_uid = t1. uid ))  as  sum_money

from  p_user  t1 

INNER  JOIN  ( select  referrer_uid, count (* )  as  count  from  p_user  where  referrer_uid > 0  GROUP  BY  referrer_uid )  t2

on  t1. uid = t2. referrer_uid

ORDER  BY  use_money  desc

执行时间9.6S,毫无疑问那个双层子查询拖慢了速度,改变一下:

SELECT  t2. referrer_uid, t1. username, t2. count,

( SELECT  sum ( use_money )  from  p_account_log  where  change_type = 3  and  p_account_log. uid = t1. uid )  as  use_money,

SUM ( t3. sum_money )  as  sum_money

from  p_user  t1 

INNER  JOIN  ( select  referrer_uid, count (* )  as  count  from  p_user  where  referrer_uid > 0  GROUP  BY  referrer_uid )  t2

on  t1. uid = t2. referrer_uid

INNER  JOIN 

( SELECT  m1. uid, m2. referrer_uid, m2. username, sum ( sum_money )  as  sum_money  from  p_order  m1

INNER  JOIN  p_user  m2  on  m1. uid = m2. uid  and  m2. referrer_uid > 0

GROUP  BY  m1. uid, m2. referrer_uid )  t3 

on  t3. referrer_uid = t2. referrer_uid

group  by  t2. referrer_uid

ORDER  BY  use_money  desc

执行时间0.2S,啊哦,本来还想着把提成金额也分解出来,看情况不用了。
结论:子查询尽量别滥用!

正文到此结束
Loading...