J'utilise SQLAlchemy avec le paragdim ORM. Je n'arrive pas à trouver un moyen de faire une instruction CASE WHEN. Je ne trouve pas d'informations à ce sujet sur le web.
C'est possible ?
Voir sqlalchemy.sql.expression.case function et plus d’exemples sur la page de documentation. Mais cela ressemblerait à ceci (textuellement de la documentation liée à):
case([(orderline.c.qty > 100, item.c.specialprice),
(orderline.c.qty > 10, item.c.bulkprice)
], else_=item.c.regularprice)
case(value=emp.c.type, whens={
'engineer': emp.c.salary * 1.1,
'manager': emp.c.salary * 3,
})
edit-1 : (répondant au commentaire)} Bien sûr, voyez l'exemple ci-dessous:
class User(Base):
__table= 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
first_name = Column(String)
last_name = Column(String)
xpr = case([(User.first_name != None, User.first_name + " " + User.last_name),],
else_ = User.last_name).label("full_name")
qry = session.query(User.id, xpr)
for _usr in qry:
print _usr.fullname
Voir aussi Utilisation d’un hybride pour obtenir un exemple de case
utilisé dans les propriétés hybrides.
Voici le lien dans la doc: http://docs.sqlalchemy.org/en/latest/core/sqlelement.html?highlight=case#sqlalchemy.sql.expression.Case
mais cela m'a dérouté de voir ces exemples, et il n'y a pas de code exécutable. J'ai essayé plusieurs fois et j'ai rencontré beaucoup de problèmes.
Enfin, j'ai trouvé deux façons d'implémenter "Case when" dans sqlalchemy.
La première façon:
En passant, j’ai besoin de masquer le champ du téléphone en fonction de la connexion de l’utilisateur.
@staticmethod
def requirement_list_common_query(user=None):
`enter code here` phone_mask = case(
[
(db.true() if user else db.false(), Requirement.temp_phone),
],
else_=func.concat(func.left(Requirement.temp_phone, 3), '****', func.right(Requirement.temp_phone, 4))
).label('temp_phone')
query = db.session.query(Requirement.company_id,
Company.uuid.label('company_uuid'),
Company.name.label('company_name'),
Requirement.uuid,
Requirement.title,
Requirement.content,
Requirement.level,
Requirement.created_at,
Requirement.published_at,
Requirement.end_at,
Requirement.status,
# Requirement.temp_phone,
phone_mask,
User.name.label('user_name'),
User.uuid.label('user_uuid')
)
query = query.join(Company, Company.id == Requirement.company_id) \
.join(User, User.id == Requirement.user_id)
return query
L'exigence est l'un de mes modèles. l'argument de l'utilisateur dans la méthode 'require_list_common_query' est l'utilisateur connecté, s'il s'est connecté.
la deuxième façon: l’occasion est que je veux classer les employés en fonction de leurs revenus.
les modèles sont:
class Dept(Base):
__table= 'dept'
deptno = Column(Integer, primary_key=True)
dname = Column(String(14))
loc = Column(String(13))
def __repr__(self):
return str({
'deptno': self.deptno,
'dname': self.dname,
'loc': self.loc
})
class Emp(Base):
__table= 'emp'
empno = Column(Integer, primary_key=True)
ename = Column(String(10))
job = Column(String(9))
mgr = Column(Integer)
hiredate = Column(Date)
sal = Column(DECIMAL(7, 2))
comm = Column(DECIMAL(7, 2))
deptno = Column(Integer, ForeignKey('dept.deptno'))
def __repr__(self):
return str({
'empno': self.empno,
'ename': self.ename,
'job': self.job,
'deptno': self.deptno,
'comm': self.comm
})
Voici le code:
from sqlalchemy import text
income_level = case(
[
(text('(emp.sal + ifnull(emp.comm,0))<1500'), 'LOW_INCOME'),
(text('1500<=(emp.sal + ifnull(emp.comm,0))<3500'), 'MIDDLE_INCOME'),
(text('(emp.sal + ifnull(emp.comm,0))>=3500'), 'HIGH_INCOME'),
], else_='UNKNOWN'
).label('income_level')
emps = sess.query(Emp.ename, label('income', Emp.sal + func.ifnull(Emp.comm, 0)),
income_level).all()
for item in emps:
print(item.ename, item.income, item.income_level)
pourquoi ai-je utilisé "texte"? Parce qu'un tel code dans SQLAlchemy 1.2.8 ne peut pas être implémenté. J'ai essayé si longtemps et je n'arrive pas à trouver un moyen comme celui-ci, comme @van l'a dit:
case([(orderline.c.qty > 100, item.c.specialprice),
(orderline.c.qty > 10, item.c.bulkprice)
], else_=item.c.regularprice)
case(value=emp.c.type, whens={
'engineer': emp.c.salary * 1.1,
'manager': emp.c.salary * 3,
})
espère que cela aidera!