2012-07-09 13 views
6

Ho due tabelle beard e moustache definito di seguito:right outer join in SQLAlchemy

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

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

ho creato una query SQL in PostgreSQL che combinerà queste due tabelle e generare seguente risultato:

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

Query:

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" 

Tuttavia non riesco a creare la rappresentazione SQLAlchemy di esso. Ho provato diversi modi dall'implementazione di from_statement a outerjoin ma nessuno di questi ha funzionato davvero. Qualcuno può aiutarmi con questo?

+0

Che cosa significa che la clausola "ON" significare? –

+0

non sta verificando l'implementazione di 'join' –

+0

Perché vuoi che il risultato sia rappresentato in questo formato piuttosto che una classe' Person' e due relazioni 'Person.beards' e' Person.mustashes'? Fondamentalmente la mia domanda è: perché usare 'sqlalchemy' per fare qualcosa così' SQL'? Se hai definito delle relazioni, potresti semplicemente rilasciare 'session.query (Person) .options (joinload ('beards')). Options (joinload ('mustashes')). All()', e la query generata sarà molto simile, ma il risultato sarebbe ancora un'istanza di 'Persona' e non una' tupla'. – van

risposta

2

Da @Francis P s' suggestion sono arrivato fino a questo frammento:

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() 

Tuttavia questo funziona, ma non si può chiamare come una risposta perché appare come un hack. Questo è un altro motivo per cui ci dovrebbe essere RIGHT OUTER JOIN in sqlalchemy.

-1

Perché non utilizzare questa semplice query:

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

Problema qui non sta scrivendo SQL Query di esso. Si trova in come rendere la rappresentazione SQLAlchemy di esso. Anche la risposta che hai dato è qualcosa di difficile da scrivere in SQLAlchemy. Sarebbe fantastico se tu lo potessi scrivere in SQLAlchemy. –

+1

è di qualche aiuto? http://stackoverflow.com/questions/7971798/sqlalchemy-union-with-different-number-of-columns –

+0

sì, è stato utile. Grazie :) –

1

Ecco quello che ho, lo stile 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) 

che sembra funzionare su di essa la propria, ma sembra essere impossibile unirsi con un'altra espressione di selezione

+0

Quando dovrebbe essere usato questo stile ('select') al posto del modo" normale "(' session.query')? –

+0

@MatthewMoisen: per quanto ne so, non è possibile inserire un '.query' all'interno di una clausola from. – Eric