【问题标题】:Calculated boolean column showing if column is newest计算的布尔列显示列是否是最新的
【发布时间】:2021-08-19 11:41:04
【问题描述】:

我有一个表,其结构或多或少(我已针对问题对其进行了简化)如下所示:

id (P.K.) creation_ts some_field
1 2021-08-19 foo
2 2021-08-18 foo
3 2021-08-17 foo
4 NULL bar
5 2021-01-01 bar
6 2021-01-02 bar

我正在尝试构建一个查询来显示一个计算列,该列每行具有相同的 "some_field" 值(呃...如果可以的话,按 "some_field" 的值分组?)会添加一个额外的is_newest 列显示哪一行是最新的。

id (P.K.) creation_ts some_field is_newest
1 2021-08-19 foo TRUE
2 2021-08-18 foo FALSE
3 2021-08-17 foo FALSE
4 NULL bar FALSE
5 2021-01-01 bar FALSE
6 2021-01-02 bar TRUE

这样做的目的是创建一个 SqlAlchemy Hybrid property,以便我们可以快速查询诸如 “get me the latest record WHERE some_field = 'foo'”之类的内容

我想这一定是某种CASE 声明(至少这是我从this other S.O. answer 收集到的,看起来很有希望)但我能想到的最好的东西是这样的:

    @is_newest.expression
    def is_newest(cls):
        subq = sa.sql.exists().where(
            sa.and_(
                cls.id != cls.id,
                cls.some_field == cls.some_field,
                # Dirty trick: If there aren't newer records than this one,
                # then this must be the newest
                cls.creation_ts > cls.creation_ts,
            )
        )
        return sa.case([(subq, False)], else_=True).label("is_newest")

但不是:这对我来说似乎很错误(而且它不起作用,因为某些单元测试失败了),因为它会产生类似...的查询

SELECT table.id, table.creation_ts, table.some_field
 FROM table WHERE 
  CASE WHEN (EXISTS (
    SELECT * FROM table WHERE 
       table.id != table.id 
       AND table.some_field = table.some_field
       AND table.creation_ts > table.creation_ts)
    ) THEN False 
    ELSE True END IS true 
AND table.some_field = 'foo'

...看起来不太对劲。虽然说实话,我不太确定“看起来不错”(我是 Postgres 的新手)

任何提示将不胜感激。提前谢谢你

【问题讨论】:

    标签: python postgresql sqlalchemy subquery calculated-columns


    【解决方案1】:

    您可以将此窗口函数查询用作本机:

    select the_table.*, 
     coalesce(creation_ts = max(creation_ts) over (partition by some_field), false) is_newest
    from the_table;
    

    或者(更好)用它创建一个视图,然后使用视图而不是表格。 结果:

    id|creation_ts|some_field|is_newest|
    --+-----------+----------+---------+
     1|2021-08-19 |foo       |true     |
     2|2021-08-18 |foo       |false    |
     3|2021-08-17 |foo       |false    |
     4|           |bar       |false    |
     5|2021-01-01 |bar       |false    |
     6|2021-01-02 |bar       |true     |
    

    编辑
    is_newest 表达式中添加了coalesce

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      • 2013-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多