Невозможно преобразовать эту строку SQL (со значениями ... AS) в код SQLAlchemy - PullRequest
0 голосов
/ 08 мая 2018

SQL-запрос, который я имею, может идентифицировать Max время редактирования из 3 таблиц, которые он объединяет:

Select Identity.SSN, Schedule.First_Class, Students.Last_Name,
(SELECT Max(v)
    FROM (VALUES (Students.Edit_DtTm), (Schedule.Edit_DtTm),
    (Identity.Edit_DtTm)) AS value(v)) as [MaxEditDate]
FROM Schedule
LEFT JOIN Students ON Schedule.stdnt_id=Students.Student_Id
LEFT JOIN Identity ON Schedule.std_id=Identity.std_id

Мне нужно, чтобы это было в SQLAlchemy, чтобы я мог ссылаться на столбцы, используемые в других местах моего кода. Ниже приведена самая простая версия того, что я пытаюсь сделать, но это не работает. Я попытался изменить способ запроса, но я либо получаю ошибку SQL, в которой я использую VALUES неправильно, либо она не присоединяется должным образом и возвращает мне самое высокое значение в этих столбцах, не сопоставляя его с внешним запросом.

max_edit_subquery = sa.func.values(Students.Edit_DtTm, Schedule.Edit_DtTm, Identity.Edit_DtTm)
base_query = (sa.select([Identity.SSN, Schedule.First_Class, Students.Last_Name,
                            (sa.select([sa.func.max(self.max_edit_subquery)]))]).
                            select_from(Schedule.__table__.join(Students, Schedule.stdnt_id == Students.stdnt_id).
                            join(Ident, Schedule.std_id == Identity.std_id)))

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

У меня была похожая проблема, и я решил, используя следующий подход. Я добавил полный код и результирующий запрос. Код был выполнен на сервере MSSQL. Я использовал разные таблицы и маскировал их таблицами и столбцами, указанными в приведенном ниже фрагменте кода.

from sqlalchemy import *
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.types import String
from sqlalchemy.sql.expression import FromClause


class values(FromClause):
    def __init__(self, *args):
        self.column_names = args


@compiles(values)
def compile_values(element, compiler, asfrom=False, **kwrgs):
    values = "VALUES %s" % ", ".join("(%s)" % compiler.render_literal_value(elem, String()) for elem in element.column_names)
    if asfrom:
        values = "(%s)" % values
    return values


base_query = self.db_session.query(Schedule.Edit_DtTm.label("Schedule_Edit_DtTm"),
                                 Identity.Edit_DtTm.label("Identity_Edit_DtTm"),        
                                 Students.Edit_DtTm.label("Students_Edit_DtTm"),
                                 Identity.SSN                            
                                 ).outerjoin(Students, Schedule.stdnt_id==Students.Student_Id
                                 ).outerjoin(Identity, Schedule.std_id==Identity.std_id).subquery()

values_at_from_clause = values(("Students_Edit_DtTm"), ("Schedule_Edit_DtTm"), ("Identity_Edit_DtTm")
                                ).alias('values(MaxEditDate)')

get_max_from_values = self.db_session.query(func.max(text('MaxEditDate'))
                                            ).select_from(values_at_from_clause)

output_query = self.db_session.query(get_max_from_values.subquery()
                                     ).label("MaxEditDate")

**print output_query**


SELECT
    anon_1.Schedule_Edit_DtTm AS anon_1_Schedule_Edit_DtTm,
    anon_1.Students_Edit_DtTm AS anon_1_Students_Edit_DtTm,
    anon_1.Identity_Edit_DtTm AS anon_1_Identity_Edit_DtTm,
    anon_1.SSN AS anon_1_SSN
    (
        SELECT
            anon_2.max_1
        FROM
            (
                SELECT
                    max( MaxEditDate ) AS max_1
                FROM
                    (
                    VALUES (Students_Edit_DtTm),
                           (Schedule_Edit_DtTm),
                           (Identity_Edit_DtTm)
                       ) AS values(MaxEditDate)
            ) AS anon_2
    ) AS MaxEditDate
FROM
    (
        SELECT
            Schedule.Edit_DtTm AS Schedule_Edit_DtTm,
            Students.Edit_DtTm AS Students_Edit_DtTm,
            Identity.Edit_DtTm AS Identity_Edit_DtTm,
            Identity.SSN AS SSN
        FROM
            Schedule WITH(NOLOCK)
        LEFT JOIN Students WITH(NOLOCK) ON
            Schedule.stdnt_id==Students.Student_Id
        LEFT JOIN Identity WITH(NOLOCK) ON
            Schedule.std_id==Identity.std_id
    ) AS anon_1
0 голосов
/ 08 мая 2018

Я не эксперт по SQLAlchemy, но вы можете обменять VALUES на UNION ALL:

Select Identity.SSN, Schedule.First_Class, Students.Last_Name,
(SELECT Max(v)
    FROM (SELECT Students.Edit_DtTm AS v
         UNION ALL SELECT Schedule.Edit_DtTm
         UNION ALL SELECT Identity.Edit_DtTm) s
   ) as [MaxEditDate]
FROM Schedule
LEFT JOIN Students ON Schedule.stdnt_id=Students.Student_Id
LEFT JOIN Identity ON Schedule.std_id=Identity.std_id;

Другой подход заключается в использовании функции GREATEST (недоступно в T-SQL):

Select Identity.SSN, Schedule.First_Class, Students.Last_Name,
    GREATEST(Students.Edit_DtTm, Schedule.Edit_DtTm,Identity.Edit_DtTm)
    as [MaxEditDate]
FROM Schedule
LEFT JOIN Students ON Schedule.stdnt_id=Students.Student_Id
LEFT JOIN Identity ON Schedule.std_id=Identity.std_id;

Я надеюсь, что это поможет вам перевести его на версию ORM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...