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

HH MySQL python会用JOIN,却不懂编程的“程序员”(3)已关闭评论7,4814字数 3494阅读11分38秒阅读模式

1.1. 前言

对于之前那种每一个功能都要将SQL语句分成简单语句,取出数据再拼凑。这种方法肯定不是我们想要的结构。这样对任何人都没有好处。而且如果有增加了需求,比如需要查询某个用户在某个店铺下了什么订单。这是我们又要写一遍简单的获取用的信息和订单信息的SQL。这样做显然会让我们的程序边的冗长。

1.2. 改进思路

这时候我们已经把SQL的粒度降低到了最小,说明的每个SQL的复用性将会很高。这时候我们就需要想到分装了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

1.3. 我对分装的理解

复用性高,使用平凡的功能,创建一个方法将它包装起来,提供给其他人调用。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

1.4. 需要分装什么

很明显我们需要将每个拆分的SQL进行分装变成一个方法。为了我们更加方便的使用。这样我们在获取数据的时候就不需要关心SQL是如何编写的了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

1.5. 程序实现

该程序我将拆分的SQL分表分装在4个方法中。如下表所示:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

分装的方法 方法功能
get_user_info 通过用户ID获得“用户”信息
get_order_info 通过用户ID获得“订单”信息
get_order_good_info 通过订单ID获得“订单商品”信息
get_coupon_info 通过订单ID获得“订单使用的券”信息

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

其中有一个业务方法(get_order_detail)实现了用户订单相关信息的获取:完整代码如下:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import pandas as pd
import mysql.connector
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_id});
  '''.format(user_id = ','.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_id});
  '''.format(user_id = ','.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 get_order_detail(user_id, conn=None):
  '''
  拼凑订单信息
  '''
  user_ids = [str(user_id)]
  # 获得用户信息
  user_info       = get_user_info(user_ids, conn=conn)
  # 获得订单信息
  order_info      = get_order_info(user_ids, conn=conn)
  # 获得订单ID
  order_ids       = order_info['order_id'].astype(str)
  # 获得订单商品信息
  order_good_info = get_order_good_info(order_ids, conn=conn)
  # 获得券
  coupon_info     = get_coupon_info(order_ids, conn=conn)
  # 用户信息 + 订单信息
  new_data_1 = user_info.merge(order_info, 
                               left_on='user_id', 
                               right_on='user_id', 
                               how='left')
  # new_data_1 + 订单商品信息
  new_data_2 = new_data_1.merge(order_good_info,
                                left_on='order_id',
                                right_on='order_id',
                                how='left')
  # new_data_2 + 券信息
  new_data_3 = new_data_2.merge(coupon_info, 
                                left_on='order_id', 
                                right_on='order_id', 
                                how='left')
  return new_data_3
 
 
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_3/

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

源代码:no_join_2文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

上的代码显然让人一看,有一种想自杀的心都有了,不是说会变的简单么怎么,看上去代码还是那么多,而且还引入了分装,这到底是什么鬼!!!此时此刻的我只能“额......”。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

麻烦大家先抛开代码还是很多的缺点,我们再来分析一下,如果现在的需求变了,说前台不用显示券的信息。这时候我们是不是只需要将get_order_detail方法中有关券的东西给注释掉就好了,而不需要去看之前的SQL是如何写的。如果,需求有变了说,需要显示每个订单是属于哪个门店的(假设我们这里有门店表,并且订单中有“门店ID”)。是不是只需要分装一个类似的get_store_info方法来回去门店信息(这个方法里面还是简单的SQL)。并只要在业务方法get_order_detail中调用get_store_info方法并将结果和之前的结果进行拼凑就好。这时候是不是连之前的SQL都不需要看只需要知道之前的输出是什么。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

(提示:需求变更的时候,需要修改代码时,发现要看很长的SQL的时候,往往是很痛苦的。并且如果是修改自己编写的SQL还好,如果是交给其他人来修改。我只能说:“兄弟辛苦你了,为了你的不吃亏。你也写复杂SQL让给别人改吧。这样你的心情应该会好”)文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

如果大家文章看到这里,觉得要使用拆分SQL能很好的应付业务的变更这一点没有打动你。你的问题关注在我要代码少。那就请你往下看了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_3/

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

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

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

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

weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
HH
  • 本文由 发表于 26/04/2016 00:26:28
  • 转载请务必保留本文链接:https://www.ttlsa.com/mysql/using_join_no_programing_3/