1.排除法
在写代码的时候,我们经常会遇到这种情况,就是代码逻辑本身比较复杂,然后呢debug过程中还发现了一些很诡异的错误,比如如下python代码,其中Class 是班级对象,而 Student是学生对象,他们是一对多关系:
1.1.对象信息
class Class(Base):
__tablename__ = 't_class'
id = Column(INTEGER, primary_key=True, autoincrement=True)
name = Column(String(32))
def __init__(self, id=None, name=None):
self.id = id
self.name = name
class Student(Base):
__tablename__ = 't_student'
id = Column(INTEGER, primary_key=True, autoincrement=True)
name = Column(String(32))
c_id = Column('c_id', INTEGER)
def __init__(self, id=None, name=None, c_id=c_id):
self.id = id
self.name = name
self.c_id = c_id
2.获取数据库连接
class DBManager(object):
@staticmethod
def get_session():
# postgresqls
# engine = create_engine('postgresql://postgres:123456@10.74.12.202:5432/test', echo=True)
# mysql
engine = create_engine('mysql+mysqlconnector://root:123456@10.74.12.202:3306/test',
echo=False, encoding="utf-8", max_overflow=30, pool_size=10)
DBsession = sessionmaker(bind=engine)
# 初始化表
return DBsession()
3.数据库信息
4.正常查询语句和结果
5.使用sqlalchemy查询语句
正常查询
def combine_query():
"""
联合查询
:return:
"""
session = DBManager.get_session()
query = session.query(Student.id, Student.name, Class.name).filter(Student.c_id == Class.id)
rows = query.all()
for row in rows:
print row[0], row[1], row[2]
添加条件查询:添加 in 查询
def combine_query():
"""
联合查询
:return:
"""
session = DBManager.get_session()
query = session.query(Student.id, Student.name, Class.name).filter(Student.c_id == Class.id)
ids = []
query = query.filter(Student.id.in_(ids))
rows = query.all()
for row in rows:
print row[0], row[1], row[2]
这个查询被 sqlalchemy 编译后的结果如下:
SELECT t_student.id AS t_student_id, t_student.name AS t_student_name, t_class.name AS t_class_name
FROM t_student, t_class
WHERE t_student.c_id = t_class.id AND t_student.id != t_student.id
注意where条件这一块多了如下的内容 AND t_student.id != t_student.id,这个很明显是有问题的,所以导致查询出错,因为这个查询很简单,所以如果多看看可能就把问题解决了。
但是如果这是一个非常复杂的查询,里面掺杂了各种查询条件,这个时候估计再来分析可能难度就会变得非常大,怎么办呢?比如如果代码如下:
def combine_query():
"""
联合查询
:return:
"""
session = DBManager.get_session()
query = session.query(Student.id, Student.name, Class.name).filter(Student.c_id == Class.id)
ids = []
query = query.filter(Student.name.like('小明'))
query = query.filter(Student.c_id > 10)
query = query.filter(Student.id.in_(ids))
rows = query.all()
for row in rows:
print row[0], row[1], row[2]
这个时候,代码还是很简单,我们可以想象如果条件不是几个,而是几十个怎么办呢?对于这种复杂的问题,诡异的问题,不要去分析逻辑,那样太耗时了,直接使用排除法来解决,就是把所有条件都先删除掉,然后逐个添加条件,当添加某个条件后出现诡异问题了,那就说明问题就出现在这个条件上,然后就定位到问题了,解决的办法也就来了,这样的效率要比分析的效率高很多,因为掺杂逻辑的关联可能让分析变得非常麻烦和复杂,这种排除法反而简单而且容易分析。
对应上面这个问题,只要我们一个条件一个条件的添加,会发现出现AND t_student.id != t_student.id的时候是在添加: query = query.filter(Student.id.in_(ids)) 条件的时候,所以就知道是因为 ids 是空的时候会出现这种问题,于是我们就可以通过判断来决定是不是要添加这个条件了,我们可以修改如下。
def combine_query():
"""
联合查询
:return:
"""
session = DBManager.get_session()
query = session.query(Student.id, Student.name, Class.name).filter(Student.c_id == Class.id)
ids = []
query = query.filter(Student.name.like('小明'))
query = query.filter(Student.c_id > 0)
query = query.filter(Student.id.in_(ids) if ids else '')
rows = query.all()
for row in rows:
print row[0], row[1], row[2]
如上可知道,我们使用的框架本身可能存在一些问题,这个时候如果我们正好碰上了,我们可能会感觉很受挫,这个时候,与其通过所谓的理性去查找问题,不如通过排除法来快速定位和解决问题,这会让我们解决问题的效率有很大提升。