2014-03-27 118 views
3

我有三個表。這些與ForeignKey約束相結合,sqlalchemy知道如何加入它們。選擇多個連接

我想從所有三個表選擇列:

select([a.c.x, b.c.x, c.c.x], a.c.a.between(10,20), [join(a, c), join(a, b)]) 

這會產生破SQL:

SELECT a.x, b.x, c.x 
FROM 
    a JOIN b ON a.b_id == b.id, 
    a JOIN c ON a.c_id == c.id 
WHERE 
    a.a BETWEEN 10 AND 20; 

可以看出,表aFROM子句中的兩倍!

如何使用sqlalchemy加入select()語句中的三個表?

+0

我不熟悉SQLAlchemy,但您可能想嘗試[查詢](http://docs.sqlalchemy.org/en/rel_0_9/orm/query.html#sqlalchemy.orm.query.Query.join )而不是 – J0HN

回答

0

給下面一個去。

SELECT a.x, b.x, c.x 
FROM *TABLENAME* a 
JOIN *TABLENAME* b 
ON a.id = b.id 
JOIN *TABLENAME* c 
ON a.id = c.id 
WHERE 
a.a BETWEEN 10 AND 20 
1

簡短的回答是

select([a.c.x, b.c.x, c.c.x]).\ 
     select_from(a.join(b).join(c)).\ 
     where(between(a.c.a, 5, 15)) 

如果有人想對這裏嘗試一下就是整個事情。

import sqlalchemy 
    from sqlalchemy import Table, Column, Integer, String, Sequence,\ 
     ForeignKey, select, between 


    meta = sqlalchemy.MetaData() 
    url = 'sqlite:///:memory:' 
    engine = sqlalchemy.create_engine(url) 


    a = Table(
     'a', meta, 
     Column('id', Integer, Sequence('a_id_seq'), primary_key=True), 
     Column('age', Integer), 
     Column('name', String(20)) 
    ) 

    b = Table(
     'b', meta, 
     Column('a_id', Integer, ForeignKey("a.id")), 
     Column('value', String(20)) 
    ) 

    c = Table(
     'c', meta, 
     Column('a_id', Integer, ForeignKey("a.id")), 
     Column('title', String(20)) 
    ) 

    # Create tables 
    meta.create_all(engine) 

    # Fill with dummy data 
    def add_data(age, name, value, title): 
     q = a.insert().values({a.c.age: age, a.c.name: name}) 
     res = engine.execute(q) 
     a_id = res.inserted_primary_key[0] 

     q = b.insert().values({b.c.a_id: a_id, b.c.value: value}) 
     engine.execute(q) 

     q = c.insert().values({c.c.a_id: a_id, c.c.title: title}) 
     engine.execute(q) 

    add_data(12, 'Foo', 'Bar', 'Baz') 
    add_data(17, '111', '222', '333') 

    q = select([a.c.name, b.c.value, c.c.title]).\ 
     select_from(a.join(b).join(c)).\ 
     where(between(a.c.age, 5, 15)) 

    print(str(q)) 
    # SELECT a.name, b.value, c.title 
    # FROM a JOIN b ON a.id = b.a_id JOIN c ON a.id = c.a_id 
    # WHERE a.age BETWEEN :age_1 AND :age_2 

    res = engine.execute(q) 
    for row in res.fetchall(): 
     print(row) 
     # ('Foo', 'Bar', 'Baz') 

更新的答案,thx評論Will

+0

'從a,b,c'是笛卡爾產品!你需要'WHERE'或'JOIN'。 – Will

+0

哦,完全正確。容易錯過只有一行/表:) 我已經更新了答案,請看看我現在是否更好。 – MyGGaN

+0

如果b和c有關係,或者兩個表之間存在多個關係,該怎麼辦? – Will