Как использовать union в SQLAlchemy для объединения двух и более таблиц с неограниченным количеством общих связей?

Нужно объединить две разных модели у которых есть общий ключ с третьей моделью.
Описание моделей
class Income_Fact(db.Model):
    __tablename__ = 'Income_Fact'
    id = db.Column(
        UUID,
        default=text('uuid_generate_v4()'),
        server_default=text('uuid_generate_v4()'),
        primary_key=True
        )
    codes = db.Column(
        UUID,
        db.ForeignKey('Code.id'),
        nullable=True
        )
    date = db.Column(
        db.Date,
        nullable=False
        )
    value = db.Column(
        db.Float,
        nullable=False
        )

class Income_Plan(db.Model):
    __tablename__ = 'Income_Plan'
    id = db.Column(
        UUID,
        default=text('uuid_generate_v4()'),
        server_default=text('uuid_generate_v4()'),
        primary_key=True
        )
    codes = db.Column(
        UUID,
        db.ForeignKey('Code.id'),
        nullable=True
        )
    date = db.Column(
        db.Date,
        nullable=False
        )
    value = db.Column(
        db.Float,
        nullable=False
        )

class Code(db.Model):
    __tablename__ = 'Code'
    id = db.Column(UUID, default=text('uuid_generate_v4()'), server_default=text('uuid_generate_v4()'), primary_key=True)
    parents = db.Column(
        'parent_id',
        UUID,
        db.ForeignKey(id),
        default=None
        )
    code = db.Column(
        db.String,
        nullable=False
        )
    name = db.Column(
        db.String,
        nullable=False
        )
    popup = db.Column(
        db.String,
        nullable=True
        )
    income_plan_values = db.relationship(
        'Income_Plan',
        order_by='Income_Plan.date',
        backref='Code'
        )
    income_fact_values = db.relationship(
        'Income_Fact',
        order_by='Income_Fact.date',
        backref='Code'
        )



Если вызывать запрос вот так:
q1 = query(Income_Plan.value.label('plan'), literal_column("0").label('fact'), Code.id, Code.name).select_from(Income_Plan).outerjoin(Code))
q2 = query(literal_column("0").label('plan'), Income_Plan.value.label('fact'), Code.id, Code.name).select_from(Income_Fact).outerjoin(Code))
sq = q1.union_all(q2).subquery()
query(func.sum(sq.c.plan), func.sum(sq.c.fact), Income_Code.name, Income_Code.id).select_entity_from(sq).group_by(Income_Code.id, Income_Code.name)

Код на SQL генерируется вот такой
SELECT 
  sum(anon_1.plan) AS sum_1, 
  sum(anon_1.fact) AS sum_2, 
  anon_1."Code_name" AS "anon_1_Code_name",
  anon_1."Code_id" AS "anon_1_Code_id"
FROM (
  SELECT 
    anon_2.plan AS plan, anon_2.fact AS fact, 
    anon_2."Code_id" AS "Code_id",
    anon_2."Code_name" AS "Code_name"
  FROM (
        SELECT
          "Income_Plan".value AS plan,
          0 AS fact, "Code".id AS "Income_Code_id",
          "Code".name AS "Code_name"
        FROM  "Income_Plan"
          LEFT OUTER JOIN "Code" ON "Code".id = "Income_Plan".codes
        UNION ALL
        SELECT
          0 AS plan,
          "Income_Fact".value AS fact,
          "Code".id AS "Code_id",
          "Code".name AS "Code_name"
        FROM "Income_Fact"
          LEFT OUTER JOIN "Code" ON "Code".id = "Income_Fact".codes
       ) AS anon_2
     ) AS anon_1 
GROUP BY anon_1."Code_id", anon_1."Code_name"



Что нужно поменять чтобы на выходе получить хотя бы приблизительно следующее:
SELECT *
FROM (
    SELECT SUM(Income_Plan.value) as 'plan', 0 as 'plan', Code.name
        FROM Income_Plan LEFT JOIN Code ON Code.id = Income_Plan.codes
        GROUP BY Code.id;
    UNION ALL;
    SELECT SUM(Income_Facr.value) as 'plan', 0 as 'fact', Code.name
        FROM Income_Plan LEFT JOIN Code ON Code.id = Income_Plan.codes
        GROUP BY Code.id;
)

Как это сделать с помощью SQLAlchemy?
  • Вопрос задан
  • 1954 просмотра
Пригласить эксперта
Ответы на вопрос 1
@Sushkov
">alert("yohoho")
Для массивных запросов советую использовать метод execute, чем городить через ORM

Вот пример из фласка:
from flask.ext.sqlalchemy import SQLAlchemy 
db = SQLAlchemy(app) 
db.execute('insert into entries (title, text) values (?, ?)', 
[request.form['title'], request.form['text']])
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы