在SELECT子句中使用CASE表达式

时间:2018-04-08 00:08:47

标签: python sqlalchemy

我在使用SQL生成的SQLAlchemy复制结果集时遇到了很多困难。一个很大的问题是我很难理解正确的方法来制作一个可以作为arg插入到query()中的特殊列。另一个原因是我对ORM和表达语言之间的目的和实现的差异感到困惑。

以下是我的模特:

class User(db.Model):

    id = db.Column(db.Integer, primary_key=True)

    sz_shirt_dress_sleeve = db.relationship(
    'SizeKeyShirtDressSleeve', secondary=LinkUserSizeShirtDressSleeve, backref=db.backref('users', lazy='dynamic'))

LinkUserSizeShirtDressSleeve = db.Table(
    'link_user_size_shirt_dress_sleeve',
    db.Column('size_id', db.Integer, db.ForeignKey('size_key_shirt_dress_sleeve.id'), primary_key=True),
    db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True)
)

class SizeKeyShirtDressSleeve(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    size = db.Column(db.Numeric(4,2))

我正在尝试复制此SQL:

SELECT  
    size, 
    case    WHEN link_user_size_shirt_dress_sleeve.size_id IS NOT NULL
            THEN 'true' ELSE 'false' END AS present
    FROM size_key_shirt_dress_sleeve 
    LEFT JOIN link_user_size_shirt_dress_sleeve
    ON size_key_shirt_dress_sleeve.id = link_user_size_shirt_dress_sleeve.size_id
;

我尝试过的东西没用。 (如果您在阅读这些内容时可以推断出任何有缺陷的想法,请指出它们。)

预先设置CASE

case = ([(LinkUserSizeShirtDressSleeve.c.size_id != None, True)], else_=False)

query = db.session.query(SizeKeyShirtDressSleeve.size, case)
    .outerjoin(LinkUserSizeShirtDressSleeve, SizeKeyShirtDressSleeve.id == LinkUserSizeShirtDressSleeve.size_id, )
    .filter(LinkUserSizeShirtDressSleeve.id == 1)

我的python shell发誓else_=False存在语法错误,即使我认为it's presented on the docs for case的方式相同:

>>> case = ([(LinkUserSizeShirtDressSleeve.c.size_id != None, True)], else_= False)
  File "<stdin>", line 1
    case = ([(LinkUserSizeShirtDressSleeve.c.size_id != None, True)], else_= False)
                                                                           ^
SyntaxError: invalid syntax

如果我省略else_,请滚动:

case = ([(LinkUserSizeShirtDressSleeve.c.size_id != None, True)])

query = db.session.query(SizeKeyShirtDressSleeve.size, case)
    .outerjoin(LinkUserSizeShirtDressSleeve, SizeKeyShirtDressSleeve.id == LinkUserSizeShirtDressSleeve.size_id, )
    .filter(LinkUserSizeShirtDressSleeve.id == 1)

我仍然错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/lirum/Envs/LTF-PhP3R-bs/lib/python3.6/site-packages/sqlalchemy/orm/scoping.py", line 153, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/Users/lirum/Envs/LTF-PhP3R-bs/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 1399, in query
    return self._query_cls(entities, self, **kwargs)
  File "/Users/lirum/Envs/LTF-PhP3R-bs/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 140, in __init__
    self._set_entities(entities)
  File "/Users/lirum/Envs/LTF-PhP3R-bs/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 149, in _set_entities
    entity_wrapper(self, ent)
  File "/Users/lirum/Envs/LTF-PhP3R-bs/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 3999, in __init__
    "expected - got '%r'" % (column, )
sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '[(<sqlalchemy.sql.elements.BinaryExpression object at 0x10f633240>, True)]'
>>> 

我也不理解这个错误信息。这是否意味着我需要将案例包装在Columncolumn_literal实例中?我不太了解这些,但我在文档中看到了它们,并且错误暗示了这一点。虽然,上帝,我希望它只是采取案件形成。

我正在尝试做的事情的背景:

我正在编写一个视图,该视图将生成一个页面,列出所有用户的尺寸(袖子等等),AS WELL作为所有可能的(袖子)尺寸(用户可以与多种尺寸相关联)。可能的套筒尺寸范围从30.0到38.0并且增加0.5。 例如,假设ID为1的用户与尺寸30.030.531.032.0相关联。最终,结果集看起来像这样(标题不需要):

Size        |   UserIsAssociated
--------|-------------------
30.0    |   True
30.5    |   True
31.0    |   True
31.5    |   False
32.0    |   True
32.5    |   False
33.0    |   False
...
38.0    |   False

1 个答案:

答案 0 :(得分:-2)

我无法理解这个问题......

我想你想要显示真实的&#39;如果Size id不为null,则为false

所以写下面的查询

选择s.size, 当s.size_id为null然后&#39; False&#39;别的&#39;真的&#39;以现在结束 - 或者可能是这样的 - 当s.size_id不为null然后&#39; True&#39;别的&#39;错误&#39;以现在结束 来自size_key_shirt_dress_sleeve s LEVE OUTER JOIN link_user_size_shirt_dress_sleeve m on m.id = s.size_id

或者您可以使用isnull方法,如

选择s.size, ISNULL(s.size_id,&#39;假&#39;) 来自size_key_shirt_dress_sleeve s LEVE OUTER JOIN link_user_size_shirt_dress_sleeve m on m.id = s.size_id

我希望这对你有用,谢谢!