- A+
1.1. 前言
对于之前那种每一个功能都要将SQL语句分成简单语句,取出数据再拼凑。这种方法肯定不是我们想要的结构。这样对任何人都没有好处。而且如果有增加了需求,比如需要查询某个用户在某个店铺下了什么订单。这是我们又要写一遍简单的获取用的信息和订单信息的SQL。这样做显然会让我们的程序边的冗长。
1.2. 改进思路
这时候我们已经把SQL的粒度降低到了最小,说明的每个SQL的复用性将会很高。这时候我们就需要想到分装了。
1.3. 我对分装的理解
复用性高,使用平凡的功能,创建一个方法将它包装起来,提供给其他人调用。
1.4. 需要分装什么
很明显我们需要将每个拆分的SQL进行分装变成一个方法。为了我们更加方便的使用。这样我们在获取数据的时候就不需要关心SQL是如何编写的了。
1.5. 程序实现
该程序我将拆分的SQL分表分装在4个方法中。如下表所示:
分装的方法 | 方法功能 |
get_user_info | 通过用户ID获得“用户”信息 |
get_order_info | 通过用户ID获得“订单”信息 |
get_order_good_info | 通过订单ID获得“订单商品”信息 |
get_coupon_info | 通过订单ID获得“订单使用的券”信息 |
其中有一个业务方法(get_order_detail)实现了用户订单相关信息的获取:完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#!/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() |
最后输出的结果:
1 2 3 4 5 6 7 8 9 10 11 |
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
上的代码显然让人一看,有一种想自杀的心都有了,不是说会变的简单么怎么,看上去代码还是那么多,而且还引入了分装,这到底是什么鬼!!!此时此刻的我只能“额......”。
麻烦大家先抛开代码还是很多的缺点,我们再来分析一下,如果现在的需求变了,说前台不用显示券的信息。这时候我们是不是只需要将get_order_detail方法中有关券的东西给注释掉就好了,而不需要去看之前的SQL是如何写的。如果,需求有变了说,需要显示每个订单是属于哪个门店的(假设我们这里有门店表,并且订单中有“门店ID”)。是不是只需要分装一个类似的get_store_info方法来回去门店信息(这个方法里面还是简单的SQL)。并只要在业务方法get_order_detail中调用get_store_info方法并将结果和之前的结果进行拼凑就好。这时候是不是连之前的SQL都不需要看只需要知道之前的输出是什么。
(提示:需求变更的时候,需要修改代码时,发现要看很长的SQL的时候,往往是很痛苦的。并且如果是修改自己编写的SQL还好,如果是交给其他人来修改。我只能说:“兄弟辛苦你了,为了你的不吃亏。你也写复杂SQL让给别人改吧。这样你的心情应该会好”)
如果大家文章看到这里,觉得要使用拆分SQL能很好的应付业务的变更这一点没有打动你。你的问题关注在我要代码少。那就请你往下看了。
昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)
感觉本文内容不错,读后有收获?
