【问题标题】:SQLAlchemy: Selecting one row for each distinct value of a columnSQLAlchemy:为列的每个不同值选择一行
【发布时间】:2012-11-08 05:00:41
【问题描述】:

我想为列的每个不同值分别选择一行。这里我要为col1执行它:

| ID | COL1 | COL2 |
--------------------
|  1 |    0 |    0 |
|  2 |    0 |    1 |
|  3 |    1 |   11 |
|  4 |    1 |   12 |
|  5 |    1 |   16 |

结果:

| ID | COL1 | COL2 |
--------------------
|  1 |    0 |    0 |
|  3 |    1 |   11 |

01col1 的不同值。只要返回不同的列值,我对返回哪一行并不严格(例如,不需要 id 的最小值)。

请假设模型名为 TestModel 并且所有内容都已完全映射。

【问题讨论】:

  • 在 MySQL 中,这是一个简单的GROUP BY

标签: sql sqlalchemy


【解决方案1】:

您需要为此使用子查询。而且你必须选择MINMAX函数:

SELECT * FROM TestModel
WHERE ID IN(SELECT MIN(id) 
            FROM TestModel 
            GROUP BY col1)

输出:

| ID | COL1 | COL2 |
--------------------
|  1 |    0 |    0 |
|  3 |    1 |   11 |

See this SQLFiddle


SA 版本的解决方案:

subq = (session.query(func.min(TestModel.id).label("min_id")).
        group_by(TestModel.col1)).subquery()

qry = (session.query(TestModel).
       join(subq, and_(TestModel.id == subq.c.min_id)))

【讨论】:

  • 我想要 SQLAlchemy 的语法,而不是普通的 SQL
  • @van:谢谢。其实我对 SQLAlchemy 一无所知。 :)
  • @van,请说出您查询的优点;它比我的答案更复杂,而且我没有看到明显的好处。
  • 简单:您的(由 SA 生成的 SQL)代码不适用于所有 RDBMS 系统。例如,它不会在 MSSQL 上运行。 SA 的好处之一是您的产品(可能)与 RDBMS 无关。我个人非常看重这一点。但是如果您使用MySQLsqliteOracle 或其他GROUP BY 不严格的RDBMS,那么您的代码就是完美的。不过,我不确定 ANSI SQL 的兼容性。
【解决方案2】:

这将为TestModel.col1 列的每个不同值返回TestModel 对象,就像SQL 中的GROUP BY 查询一样。

session.query( TestModel).group_by( TestModel.col1).all()

【讨论】:

  • 也许您应该再详细说明一下。纯代码答案并没有真正的帮助。
  • 我错过了什么?这似乎根本不起作用。生成的 SQL(在 postgresql 下)是SELECT "order".id AS order_id, "order".external_id AS order_external_id FROM "order" GROUP BY "order".external_id。此 SQL 不起作用,因为您在不属于 group-by 参数(order.id 等)的列上使用了聚合函数。我希望有“FIRST”或“MIN”或类似的东西。
  • 嗯,我现在将 distinct on 用于 Postgres。我也对 Postgres 没有使用“不属于分组参数的列上的聚合函数”感到困惑。请发布一个真正跨平台的答案,我会接受。
【解决方案3】:

从 SQLAlchemy 1.0 开始,您可以调用 distinct with a criterion,它允许您编写

session.query(TestModel).distinct(TestModel.col1).all()

在 Postgresql 中,这将转换为 DISTINCT ON 查询。

这不仅适用于 ORM,还适用于 SQLAlchemy Core select

【讨论】:

  • 这个解决方案对我有用,但查询似乎不如 group by 有效。我并没有真正做基准测试。但是SELECT MIN(TestModel.id) FROM TestModel GROUP BY col1 不是更有效率吗?
猜你喜欢
  • 2017-07-24
  • 1970-01-01
  • 2012-10-20
  • 2020-05-20
  • 2012-07-28
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
相关资源
最近更新 更多