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

HH MySQL python1 8,6583字数 3368阅读11分13秒阅读模式

1.1. 前言

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

下面我们就来使用“动态装饰器”来实现,让我的代码更加的少。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

1.2. 回顾和找相同

回顾之前装饰器的3个方法(join_order、join_order_good、join_coupon),细心的会发现它们里面的代码几乎是相同的,除了需要关联的字段和调用获取数据方法如下表:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

装饰器方法 装饰器中需要调用的方法 拼凑时需要关联的字段
join_order get_order_info user_id
join_order_good get_order_good_info order_id
join_coupon get_coupon_info order_id

通过比较代码和分析。我们想我们能不能将 装饰器中需要调用的方法  拼凑时需要关联的字段 通过变量的方式带入装饰器,这样我们就可以使用一个装饰器来满足所有装饰器的功能呢?答案是肯定的。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

1.3. 实现程序

我们通过实现一个动态装饰器方法(join_data)来完成我们的目标。这个装饰器有两个参数func_name、col_name:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

func_name:需要动态执行的方法名。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

col_name:两个结果集关联的字段。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

完整程序如下:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

#!/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()

最后结果:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

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文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

现在来看一下我们的业务代码。代码量上少了吧。现在的代码量将会比你的jion还少了吧一个业务只需要在方法上面不端的添加注解(annotation)就好了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

我们来看一下他的应变需求变化的能力。现在业务部需要展现券的信息了,这时我们只需要将如下代码删除了:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

@join_data('get_coupon_info', 'order_id')

现在有一个需求,订单需要展示门店的信息(订单和门店是以store_id关联)。这时我们只需要查看是否有人实现过相关的方法比如get_store_info,之后只需要在业务方法get_order_detail的头上加上注解@join_data('get_store_info', 'store_id')。然后就能满足业务的需求了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

而反过来看,如果使用join的方法写的代码。你是不是需要先看懂之前的join是怎么写的,还要考虑我的代码应该要怎么添加。而且join的代码的扩展性无疑是很差的,并且对数据库的查询的并发也会大打折扣。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

如果到了现在你们还说使用join能提高开发效率。会增加代码量的。我只能说:对不起,我错了,原谅我的无知吧。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

 文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

感觉本文内容不错,读后有收获?文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

逛逛衣服店,鼓励作者写出更好文章。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/ 文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
HH
  • 本文由 发表于 10/05/2016 00:40:42
  • 转载请务必保留本文链接:https://www.ttlsa.com/mysql/using_join_no_programing_5/
评论  1  访客  1
    • 匿名
      匿名 9

      :evil: :!: :!: aaa顶顶顶顶

    评论已关闭!