drew_dru
@drew_dru

Как использовать union и join в одном SQLAlchemy запросе?

query1
self.session.query(ID_Streets, ID_Streets_history, ID_Nps, Modify_reason)\
            .outerjoin(ID_Streets_history, text('(ID_Streets.id_np=ID_Streets_history.id_np '\
                'AND ID_Streets.id_street=ID_Streets_history.id_street)'))\
            .join(ID_Nps, ID_Nps.id_np == ID_Streets.id_np)\
            .outerjoin(Modify_reason, text('(ID_Streets_history.code_reason=Modify_reason.code_reason '\
                'AND ID_Streets_history.code_detail=Modify_reason.code_detail)'))

query2
query2 = self.session.query(\
                ID_Streets_history, ID_Nps, Modify_reason,\
                sql.null().label('id_streets_id_np'),\
                sql.null().label('id_streets_id_street'),\
                sql.null().label('id_streets_name_street'),\
                sql.null().label('id_streets_type_street'))\
                .outerjoin(ID_Nps, ID_Nps.id_np == ID_Streets_history.id_np)\
                .outerjoin(Modify_reason, text('(ID_Streets_history.code_reason=Modify_reason.code_reason '\
                    'AND ID_Streets_history.code_detail=Modify_reason.code_detail)'))\
                .group_by(ID_Nps.id_region,\
                    ID_Nps.id_atu, ID_Nps.id_selsov, ID_Nps.id_np, ID_Streets_history.id_np,\
                    ID_Streets_history.id_street, ID_Streets_history.id_row,\
                    Modify_reason.code_reason, Modify_reason.code_detail)


query = query1.union(query2)
Сгенерированный sql
SELECT anon_1.id_streets_id_np AS anon_1_id_streets_id_np,
	anon_1.id_streets_id_street AS anon_1_id_streets_id_street,
	anon_1.id_streets_name_street AS anon_1_id_streets_name_street,
	anon_1.id_streets_type_street AS anon_1_id_streets_type_street,
	anon_1.id_nps_id_region AS anon_1_id_nps_id_region,
	anon_1.id_nps_id_atu AS anon_1_id_nps_id_atu,
	anon_1.id_nps_id_selsov AS anon_1_id_nps_id_selsov,
	anon_1.id_nps_id_np AS anon_1_id_nps_id_np,
	anon_1.id_nps_name_np AS anon_1_id_nps_name_np,
	anon_1.id_nps_type_np AS anon_1_id_nps_type_np,
	anon_1.id_nps_okato AS anon_1_id_nps_okato,
	anon_1.id_nps_oktmo AS anon_1_id_nps_oktmo,
	anon_1.id_streets_history_id_np AS anon_1_id_streets_history_id_np,
	anon_1.id_streets_history_id_street AS anon_1_id_streets_history_id_street,
	anon_1.id_streets_history_id_row AS anon_1_id_streets_history_id_row,	
	anon_1.id_streets_history_name_street AS anon_1_id_streets_history_name_street,
	anon_1.id_streets_history_type_street AS anon_1_id_streets_history_type_street,
	anon_1.id_streets_history_code_reason AS anon_1_id_streets_history_code_reason,
	anon_1.id_streets_history_code_detail AS anon_1_id_streets_history_code_detail,
	anon_1.id_streets_history_creater AS anon_1_id_streets_history_creater,
	anon_1.id_streets_history_createddate AS anon_1_id_streets_history_createddate,
	anon_1.id_streets_history_updater AS anon_1_id_streets_history_updater,
	anon_1.id_streets_history_updateddate AS anon_1_id_streets_history_updateddate,
	anon_1.id_streets_history_recordcomment AS anon_1_id_streets_history_recordcomment,
	anon_1.id_streets_history_sourcecomment AS anon_1_id_streets_history_sourcecomment,
	anon_1.modify_reason_code_reason AS anon_1_modify_reason_code_reason,
	anon_1.modify_reason_code_detail AS anon_1_modify_reason_code_detail,
	anon_1.modify_reason_comment_reason AS anon_1_modify_reason_comment_reason 
FROM (SELECT id_streets.id_np AS id_streets_id_np,
	id_streets.id_street AS id_streets_id_street,
	id_streets.name_street AS id_streets_name_street,
	id_streets.type_street AS id_streets_type_street,
	id_nps.id_region AS id_nps_id_region,
	id_nps.id_atu AS id_nps_id_atu,
	id_nps.id_selsov AS id_nps_id_selsov,
	id_nps.id_np AS id_nps_id_np,
	id_nps.name_np AS id_nps_name_np,
	id_nps.type_np AS id_nps_type_np,
	id_nps.okato AS id_nps_okato,
	id_nps.oktmo AS id_nps_oktmo,
	id_streets_history.id_np AS id_streets_history_id_np,
	id_streets_history.id_street AS id_streets_history_id_street,
	id_streets_history.id_row AS id_streets_history_id_row,
	id_streets_history.name_street AS id_streets_history_name_street,
	id_streets_history.type_street AS id_streets_history_type_street,
	id_streets_history.code_reason AS id_streets_history_code_reason,
	id_streets_history.code_detail AS id_streets_history_code_detail,
	id_streets_history.creater AS id_streets_history_creater,
	id_streets_history.createddate AS id_streets_history_createddate,
	id_streets_history.updater AS id_streets_history_updater,
	id_streets_history.updateddate AS id_streets_history_updateddate,
	id_streets_history.recordcomment AS id_streets_history_recordcomment,
	id_streets_history.sourcecomment AS id_streets_history_sourcecomment,
	modify_reason.code_reason AS modify_reason_code_reason,
	modify_reason.code_detail AS modify_reason_code_detail,
	modify_reason.comment_reason AS modify_reason_comment_reason 
FROM id_streets
	JOIN id_nps ON id_nps.id_np = id_streets.id_np
	LEFT OUTER JOIN id_streets_history ON (
		ID_Streets.id_np=ID_Streets_history.id_np
		AND ID_Streets.id_street=ID_Streets_history.id_street)
	LEFT OUTER JOIN modify_reason ON (
		ID_Streets_history.code_reason=Modify_reason.code_reason
		AND ID_Streets_history.code_detail=Modify_reason.code_detail)
	GROUP BY id_streets.id_np, id_streets.id_street, id_nps.id_region, id_nps.id_atu, id_nps.id_selsov, id_nps.id_np, id_streets_history.id_np, id_streets_history.id_street, id_streets_history.id_row, modify_reason.code_reason, modify_reason.code_detail

UNION DISTINCT SELECT 
	id_nps.id_region AS id_nps_id_region, id_nps.id_atu AS id_nps_id_atu,
	id_nps.id_selsov AS id_nps_id_selsov, id_nps.id_np AS id_nps_id_np,
	id_nps.name_np AS id_nps_name_np, id_nps.type_np AS id_nps_type_np,
	id_nps.okato AS id_nps_okato, id_nps.oktmo AS id_nps_oktmo,

	id_streets_history.id_np AS id_streets_history_id_np,
	id_streets_history.id_street AS id_streets_history_id_street,
	id_streets_history.id_row AS id_streets_history_id_row,
	id_streets_history.name_street AS id_streets_history_name_street,
	id_streets_history.type_street AS id_streets_history_type_street,
	id_streets_history.code_reason AS id_streets_history_code_reason,
	id_streets_history.code_detail AS id_streets_history_code_detail,
	id_streets_history.creater AS id_streets_history_creater,
	id_streets_history.createddate AS id_streets_history_createddate,
	id_streets_history.updater AS id_streets_history_updater,
	id_streets_history.updateddate AS id_streets_history_updateddate,
	id_streets_history.recordcomment AS id_streets_history_recordcomment,
	id_streets_history.sourcecomment AS id_streets_history_sourcecomment,

	modify_reason.code_reason AS modify_reason_code_reason,
	modify_reason.code_detail AS modify_reason_code_detail,
	modify_reason.comment_reason AS modify_reason_comment_reason,
	
	NULL AS id_streets_id_np,
	NULL AS id_streets_id_street,
	NULL AS id_streets_name_street,
	NULL AS id_streets_type_street


FROM id_streets_history
	LEFT OUTER JOIN id_nps ON id_nps.id_np = id_streets_history.id_np
	LEFT OUTER JOIN modify_reason ON (
		ID_Streets_history.code_reason=Modify_reason.code_reason
		AND ID_Streets_history.code_detail=Modify_reason.code_detail)
	GROUP BY id_nps.id_region, id_nps.id_atu, id_nps.id_selsov, id_nps.id_np, id_streets_history.id_np, id_streets_history.id_street, id_streets_history.id_row, modify_reason.code_reason, modify_reason.code_detail
)AS anon_1



В postgreSql сгенерированный код не работает т.к. для UNION важен порядок колонок после SELECT.
Порядок колонок в query2 пришлось изменить т.к. sqlalchemy на такой порядок:
spoiler
self.session.query(\
                sql.null().label('id_streets_id_np'),\
                sql.null().label('id_streets_id_street'),\
                sql.null().label('id_streets_name_street'),\
                sql.null().label('id_streets_type_street'),\
                ID_Streets_history, ID_Nps, Modify_reason)


Выдаёт следующую ошибку:
Don't know how to join from NULL; please use select_from() to establish the left entity/selectable of this join


Можно ли как-то иначе исправить эту ошибку, не изменяя порядок колонок, или перед вызовом union изменить порядок колонок?
  • Вопрос задан
  • 413 просмотров
Решения вопроса 1
drew_dru
@drew_dru Автор вопроса
query1 = self.session.query(ID_Streets, ID_Streets_history, ID_Nps, Modify_reason)\
            .outerjoin(ID_Streets_history, text('(ID_Streets.id_np=ID_Streets_history.id_np '\
                'AND ID_Streets.id_street=ID_Streets_history.id_street)'))\
            .join(ID_Nps, ID_Nps.id_np == ID_Streets.id_np)\
            .outerjoin(Modify_reason, text('(ID_Streets_history.code_reason=Modify_reason.code_reason '\
                'AND ID_Streets_history.code_detail=Modify_reason.code_detail)'))

query2 = self.session.query(\
                sql.null().label('id_streets_id_np'),\
                sql.null().label('id_streets_id_street'),\
                sql.null().label('id_streets_name_street'),\
                sql.null().label('id_streets_type_street'),
                ID_Streets_history, ID_Nps, Modify_reason)\
                .select_from(ID_Streets_history, ID_Nps, Modify_reason)\
                .outerjoin(ID_Nps, ID_Nps.id_np == ID_Streets_history.id_np)\
                .outerjoin(Modify_reason, text(\
                    '(ID_Streets_history.code_reason=Modify_reason.code_reason '\
                    'AND ID_Streets_history.code_detail=Modify_reason.code_detail)'))

query = query1.union(query2)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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