【问题标题】:SQLAlchemy: create sqlalchemy query from sql query with subquery and inner joinSQLAlchemy:使用子查询和内连接从 sql 查询创建 sqlalchemy 查询
【发布时间】:2023-03-18 22:39:01
【问题描述】:

我是后端开发和 python 的新手。我正在从具有子查询和内部联接的 SQL 查询创建一个 SQLAlchemy 查询。

我正在使用 python > 3.5,“oracle+cx_oracle”驱动程序和 SQLAlchemy==1.3.6

我需要转换的SQL查询是:

SELECT DISTINCT d.*, t.max_date, t.USER_ID
FROM DATABASE_ONE d
INNER JOIN (
    SELECT USER_ID, MAX(DATE_CREATED) max_date FROM (
        SELECT * FROM DATABASE_ONE
        WHERE USER_ID IN ('1','2','3')
        AND CATEGORY = 'Users'
        AND IS_DELETED IS NULL
    )
    GROUP  BY USER_ID
) t on t.USER_ID = d.USER_ID AND t.max_date = d.DATE_CREATED

下面是我尝试将上述 SQL 查询转换为 SQLAlchemy 查询的代码。

    # --------------------- first query -------------------

    first_query = (
        Session.query(DatabaseOne)
        .filter(
            DatabaseOne.user_id.in_('1', '2', '3'),
            DatabaseOne.category == "Obligor Rating Scorecards",
            DatabaseOne.is_deleted == None,
        )
        .subquery("first_query")
    )

    # -------------------- second query --------------------

    second_query = (
        Session.query(
            DatabaseOne.user_id,
            func.max(DatabaseOne.date_created).label("max_date"),
        )
        .select_from(first_query)
        .group_by(DatabaseOne.user_id)
        .subquery("second_query")
    )

    # -------------------- final query --------------------

    final_query = (
        Session.query(
            DatabaseOne, second_query.c.max_date, second_query.c.user_id
        )
        .join(
            second_query,
            and_(
                second_query.c.user_id == DatabaseOne.user_id,
                DatabaseOne.date_created == second_query.c.max_date,
            ),
        )
        .distinct(DatabaseOne)
        .all()
    )
  • 我能够在 first_query 上获得预期结果。
  • second_query 未能给出预期结果。
  • 我不确定 final_query 是否正确。

【问题讨论】:

    标签: python oracle flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    根据您的 SQL,我认为您正在尝试查询给出 user_id 和最大日期的行。 所以首先也许我们可以稍微更新一下 SQL:

    SELECT DISTINCT d.*, t.max_date, t.USER_ID
    FROM DATABASE_ONE d
    INNER JOIN (
        SELECT USER_ID, MAX(DATE_CREATED) max_date 
        FROM DATABASE_ONE
        WHERE 
            USER_ID IN ('1','2','3')
            AND CATEGORY = 'Users'
            AND IS_DELETED IS NULL
        GROUP  BY USER_ID
    ) t on t.USER_ID = d.USER_ID AND t.max_date = d.DATE_CREATED
    

    在这种情况下,更容易阅读和转换为 SQLAlchemy 语言。


    那么关于您的第二个 SQLAlchemy 查询的问题是您试图从子查询中进行选择,但选择来自原始表。如果将第二个 SQLAlchemy 查询转换为 sql 查询,它将如下所示:

    SELECT DATABASE_ONE.USER_ID, MAX(DATABASE_ONE.DATE_CREATED) max_date FROM (
        SELECT * FROM DATABASE_ONE
        WHERE USER_ID IN ('1','2','3')
        AND CATEGORY = 'Users'
        AND IS_DELETED IS NULL
    )
    GROUP  BY DATABASE_ONE.USER_ID
    

    编写 SQLAlchemy 查询的更好方法:

        subquery = Session.query(
            DatabaseOne.user_id,
            func.max(DatabaseOne.date_created).label("max_date"),
        )
        .filter(
            DatabaseOne.user_id.in_('1', '2', '3'),
            DatabaseOne.category == "Obligor Rating Scorecards",
            DatabaseOne.is_deleted == None,
        )
        .group_by(DatabaseOne.user_id)
        .subquery()
    
        Session.query(
            DatabaseOne, subquery.c.user_id, subquery.c.max_date # see the .c method to access column in subquery
        ).select_from(subquery).join(DatabaseOne).filter(DatabaseOne.user_id = subquery.c.user_id,DatabaseOne.date_created = subquery.c.max_date).all()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-31
      • 2019-12-13
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      相关资源
      最近更新 更多