2012-07-09 98 views
6

我有两个表beardmoustache定义如下:RIGHT OUTER JOIN在SQLAlchemy的

+--------+---------+------------+-------------+ 
| person | beardID | beardStyle | beardLength | 
+--------+---------+------------+-------------+ 

+--------+-------------+----------------+ 
| person | moustacheID | moustacheStyle | 
+--------+-------------+----------------+ 

我已PostgreSQL中创建的SQL查询,这将结合这两个表,并产生如下结果:

+--------+---------+------------+-------------+-------------+----------------+ 
| person | beardID | beardStyle | beardLength | moustacheID | moustacheStyle | 
+--------+---------+------------+-------------+-------------+----------------+ 
| bob | 1  | rasputin | 1   |    |    | 
+--------+---------+------------+-------------+-------------+----------------+ 
| bob | 2  | samson  | 12   |    |    | 
+--------+---------+------------+-------------+-------------+----------------+ 
| bob |   |   |    | 1   | fu manchu  | 
+--------+---------+------------+-------------+-------------+----------------+ 

查询:

SELECT * FROM beards LEFT OUTER JOIN mustaches ON (false) WHERE person = "bob" 
UNION ALL 
SELECT * FROM beards b RIGHT OUTER JOIN mustaches ON (false) WHERE person = "bob" 

但是我无法创建它的SQLAlchemy表示形式。我尝试了几种实施from_statementouterjoin的方法,但没有一个真正起作用。任何人都可以帮助我吗?

+0

什么是“ON”条款意思? – 2012-07-09 17:50:51

+0

它没有检查执行'加入' – 2012-07-09 17:52:47

+0

为什么你想要以这种格式表示结果而不是'Person'类和两个关系'Person.beards'和'Person.mustashes'?基本上我的问题是:为什么使用'sqlalchemy'来做'SQL'这样的事情?如果你定义了关系,你可以发出'session.query(Person).options(joinedload('beards'))选项(joinedload('mustashes'))。all()',并且生成的查询将会非常相似,但结果仍然是'Person'的一个实例,而不是'tuple'。 – van 2012-07-09 21:54:35

回答

2

@Francis Psuggestion我想出了这个片断:

q1 = session.\ 
    query(beard.person.label('person'), 
      beard.beardID.label('beardID'), 
      beard.beardStyle.label('beardStyle'), 
      sqlalchemy.sql.null().label('moustachID'), 
      sqlalchemy.sql.null().label('moustachStyle'), 
    ).\ 
    filter(beard.person == 'bob') 

q2 = session.\ 
    query(moustache.person.label('person'), 
      sqlalchemy.sql.null().label('beardID'), 
      sqlalchemy.sql.null().label('beardStyle'), 
      moustache.moustachID, 
      moustache.moustachStyle, 
    ).\ 
    filter(moustache.person == 'bob') 

result = q1.union(q2).all() 

但是这个工作,但你不能把它作为一个答案因为它看起来像一个黑客。这是sqlalchemy中应该有RIGHT OUTER JOIN的另一个原因。

-1

为什么不利用这个简单的查询:

SELECT person, beardID, beardStyle, beardLength, 
     NULL AS moustacheID, NULL AS moustacheStyle 
FROM beards 
WHERE person = "bob" 

UNION 

SELECT person, NULL AS beardID, NULL AS beardStyle, NULL AS beardLength, 
     moustacheId, moustacheStyle 
FROM mustaches 
WHERE person = "bob" 
+2

此处的问题不是写它的SQL查询。它在于如何使SQLAlchemy表示它。即使你给出的答案在SQLAlchemy中编写也很棘手。如果你能够在SQLAlchemy中编写它,那将会很棒。 – 2012-07-09 18:12:48

+1

是有帮助的吗? http://stackoverflow.com/questions/7971798/sqlalchemy-union-with-different-number-of-columns – 2012-07-09 18:16:29

+0

是的,这是有帮助的。谢谢:) – 2012-07-10 09:57:05

1

下面是我得到了什么,ORM风格:

from sqlalchemy.sql import select, false 

stmt = (
    select([Beard, Moustache]) 
    .select_from(
     outerjoin(Beard, Moustache, false()) 
    ).apply_labels() 
).union_all(
    select([Beard, Moustache]) 
    .select_from(
     outerjoin(Moustache, Beard, false()) 
    ).apply_labels() 
) 

session.query(Beard, Moustache).select_entity_from(stmt) 

这似乎是在它自己的工作,但似乎是不可能与另一个选择表达加入

+0

何时应该使用这种风格('select')而不是“正常”的方式('session.query')? – 2016-09-11 04:15:35

+0

@MatthewMoisen:据我所知,你不能在from子句中放置'.query'。 – Eric 2016-09-11 04:34:07