显示列是否为最新的计算布尔列
Calculated boolean column showing if column is newest
我有一个 table 的结构或多或少(我已针对问题对其进行了简化)如下所示:
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,这样我们就可以快速查询 “给我最新的记录 WHERE some_field = 'foo'
”
我想这一定是某种 CASE
声明(至少这是我从 中收集到的,看起来很有希望)但我能想到的最好的东西是这样的:
@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 的新手)
如有任何提示,我们将不胜感激。提前谢谢你
您可以将此 window 函数查询用作本机查询:
select the_table.*,
coalesce(creation_ts = max(creation_ts) over (partition by some_field), false) is_newest
from the_table;
或者(更好)从中创建一个视图,然后使用该视图而不是 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 |
编辑
将 coalesce
添加到 is_newest
表达式。
我有一个 table 的结构或多或少(我已针对问题对其进行了简化)如下所示:
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,这样我们就可以快速查询 “给我最新的记录 WHERE some_field = 'foo'
”
我想这一定是某种 CASE
声明(至少这是我从
@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 的新手)
如有任何提示,我们将不胜感激。提前谢谢你
您可以将此 window 函数查询用作本机查询:
select the_table.*,
coalesce(creation_ts = max(creation_ts) over (partition by some_field), false) is_newest
from the_table;
或者(更好)从中创建一个视图,然后使用该视图而不是 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 |
编辑
将 coalesce
添加到 is_newest
表达式。