会用JOIN,却不懂编程的“程序员”

版权声明:此文章转载自infocool

原文链接:http://www.infocool.net/kb/Python/201607/161414.html

如需转载请联系听云College团队成员小尹 邮箱:yinhy#tingyun.com


1.1. 前言

在上一篇文章我们展示了使用装饰器来完成拆分后的编写SQL。好处是让代码变的更加的厉害,更容易的应变未来需求的变更了。但是,麻烦的是免不了需要添加新的装饰器。当然这对哪些较劲的来说肯定还说:之前的开发麻烦,代码有没减。这种效果当然也不是我想要的。

下面我们就来使用“动态装饰器”来实现,让我的代码更加的少。

1.2. 回顾和找相同

回顾之前装饰器的3个方法(join_order、join_order_good、join_coupon),细心的会发现它们里面的代码几乎是相同的,除了需要关联的字段和调用获取数据方法如下表:

装饰器方法 装饰器中需要调用的方法 拼凑时需要关联的字段

join_orderget_order_infouser_id
join_order_goodget_order_good_infoorder_id
join_couponget_coupon_infoorder_id

通过比较代码和分析。我们想我们能不能将 装饰器中需要调用的方法 和 拼凑时需要关联的字段 通过变量的方式带入装饰器,这样我们就可以使用一个装饰器来满足所有装饰器的功能呢?答案是肯定的。

1.3. 实现程序

我们通过实现一个动态装饰器方法(join_data)来完成我们的目标。这个装饰器有两个参数func_name、col_name:

func_name:需要动态执行的方法名。

col_name:两个结果集关联的字段。

完整程序如下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pandas as pd
import mysql . connector
import sys
import sys
  
reload ( sys )
sys . setdefaultencoding ( 'utf-8' )
def get_user_info ( user_ids , conn = None ) :
   '' '
  通过user_id获得用户信息
  ' ''
   user_sql = '' '
    SELECT user_id, name FROM user WHERE user_id IN({user_ids});
  ' '' . format ( user_ids = ',' . join ( user_ids ) )
   user_info = pd . read_sql ( user_sql , conn )
   return user_info
def get_order_info ( user_ids , conn = None ) :
   '' '
  通过 用户ID 获得订单信息
  ' ''
   order_sql = '' '
    SELECT user_id, order_id, num FROM orders WHERE user_id IN({user_ids});
  ' '' . format ( user_ids = ',' . join ( user_ids ) )
   order_info = pd . read_sql ( order_sql , conn )
   return order_info
  
def get_order_good_info ( order_ids , conn = None ) :
   '' '
  通过上面获得的 订单ID 获得订单商品信息。
  ' ''
   order_good_sql = '' '
    SELECT order_id, good_name FROM order_good WHERE order_id IN ({ids});
  ' '' . format ( ids = ',' . join ( order_ids ) )
   order_good_info = pd . read_sql ( order_good_sql , conn )
   return order_good_info
def get_coupon_info ( order_ids , conn = None ) :
   '' '
  通过 订单ID 获得券信息
  ' ''
   coupon_sql = '' '
    SELECT order_id, name FROM coupon WHERE order_id IN({ids});
  ' '' . format ( ids = ',' . join ( order_ids ) )
   coupon_info = pd . read_sql ( coupon_sql , conn )
   return coupon_info
def join_data ( func_name , col_name ) :
   '' '
  添加能通过订单ID查找出来的信息
  ' ''
   def _join_data ( func ) :
     def __join_data ( * args , * * kargs ) :
       func_info = func ( * args , * * kargs )
       ids = func_info [ col_name ] . astype ( str )
       info = eval ( func_name ) ( ids , * * kargs )
       new_order = func_info . merge ( info ,
                                   left_on = col_name ,
                                   right_on = col_name ,
                                   how = 'left' )
       return new_order
     return __join_data
   return _join _data
  
  
@ join_data ( 'get_coupon_info' , 'order_id' )
@ join_data ( 'get_order_good_info' , 'order_id' )
@ join_data ( 'get_order_info' , 'user_id' )
def get_order_detail ( user_id , conn = None ) :
   '' '
  拼凑获得订单信息
  ' ''
   user_ids = [ str ( user_id ) ]
   return get_user_info ( user_ids , conn = conn )
if __name__ == '__main__' :
   conf = {
     'host'      : '127.0.0.1' ,
     'port'      : '3306' ,
     'database' : 'test' ,
     'user'      : 'root' ,
     'password' : 'root'
   }
   conn = mysql . connector . connect ( * * conf )
   print get_order_detail ( 10 , conn = conn )
   conn . close ( )

最后结果:

user_id name_x   order_id     num       good_name     name _y
0        10      HH          1    11111    order_good_1   coupon _1
1        10      HH          1    11111    order_good_2   coupon _1
2        10      HH          2    22222    order_good_3       NaN
3        10      HH          2    22222    order_good_4       NaN
4        10      HH          3    33333    order_good_5   coupon _3
5        10      HH          3    33333    order_good_6   coupon _3
6        10      HH          4    44444    order_good_7       NaN
7        10      HH          4    44444    order_good_8       NaN
8        10      HH          5    55555    order_good_9   coupon _5
9        10      HH          5    55555    order_good_10   coupon_5

源代码:use_dynamic_decorator

现在来看一下我们的业务代码。代码量上少了吧。现在的代码量将会比你的jion还少了吧一个业务只需要在方法上面不端的添加注解(annotation)就好了。

我们来看一下他的应变需求变化的能力。现在业务部需要展现券的信息了,这时我们只需要将如下代码删除了:

@ join_data ( 'get_coupon_info' , 'order_id' )

现在有一个需求,订单需要展示门店的信息(订单和门店是以store_id关联)。这时我们只需要查看是否有人实现过相关的方法比如get_store_info,之后只需要在业务方法get_order_detail的头上加上注解@join_data('get_store_info', 'store_id')。然后就能满足业务的需求了。

而反过来看,如果使用join的方法写的代码。你是不是需要先看懂之前的join是怎么写的,还要考虑我的代码应该要怎么添加。而且join的代码的扩展性无疑是很差的,并且对数据库的查询的并发也会大打折扣。

如果到了现在你们还说使用join能提高开发效率。会增加代码量的。我只能说:对不起,我错了,原谅我的无知吧。

想阅读更多技术文章,请访问听云技术博客,访问听云官方网站感受更多应用性能优化魔力。

关于作者

郝淼emily

重新开始,从心开始

我要评论

评论请先登录,或注册