选择符合条件的最后一条记录

Bal*_*kai 5 postgresql

我有一个这样的简化表:

id |val |
---|----|
1  |6   |
2  |5   |
3  |4   |
4  |4   |
5  |8   |
6  |9   |
7  |7   |
Run Code Online (Sandbox Code Playgroud)

我想以选择val < 5最后一条记录的方式选择记录val >= 5。所以结果应该是这样的:

id |val |
---|----|
1  |6   |
2  |5   |
3  |5   |
4  |5   |
5  |8   |
6  |9   |
7  |7   |
Run Code Online (Sandbox Code Playgroud)

我想知道这是否可以不定义函数,所以我尝试了:

id |val |
---|----|
1  |6   |
2  |5   |
3  |4   |
4  |4   |
5  |8   |
6  |9   |
7  |7   |
Run Code Online (Sandbox Code Playgroud)

但它只返回:

id |val |
---|----|
1  |6   |
2  |5   |
3  |5   |
4  |4   |
5  |8   |
6  |9   |
7  |7   |
Run Code Online (Sandbox Code Playgroud)

是否可以在不定义函数的情况下编写此查询?还是用函数会更好?

编辑:组合解决方案

为完整起见,尽管它与原始问题描述略有不同,但我包括如果将@Andriy M 和 @Hogan 的答案组合在一起,则将保留 NULL 值,并且只有低于阈值的值将使用最后一个有效值进行更新价值。在某些情况下,希望保留 NULL 值。因此,查询将是这样的:

id |val |
---|----|
1  |6   |
2  |5   |
3  |5   |
4  |5   |
5  |8   |
6  |9   |
7  |7   |
Run Code Online (Sandbox Code Playgroud)

返回:

id |val |newval |
---|----|-------|
1  |6   |6      |
2  |5   |5      |
3  |4   |5      |
4  |NULL|NULL   |
5  |8   |8      |
6  |9   |9      |
7  |7   |7      |
Run Code Online (Sandbox Code Playgroud)

And*_*y M 2

我认为 LAG() 不能在这里使用,因为使用 LAG,您需要具体说明要返回多少行。(默认情况下为 1,但您可以指定 3、10 或任何其他数字。但重点是它必须是特定数字。)在您的情况下,您不知道最后一个匹配值是否在上一行或之前的行,甚至更早。

\n\n

因此,另一种方法是查找具有匹配值的最后一行的 ID,然后查找该 ID 以获取最终输出 \xe2\x80\x93 的值,如下所示:

\n\n
SELECT\n  s.id,\n  t.val\nFROM\n  (\n    SELECT\n      id,\n      MAX(CASE WHEN val >=5 THEN id END) OVER (ORDER BY id ASC) AS last_id\n    FROM\n      test\n  ) AS s\n  INNER JOIN test AS t ON s.last_id = t.id\nORDER BY\n  s.id ASC\n;\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,您可以使用相关子查询来获取从最低 ID 到当前 ID 的子集中最后一个大于 5 的值:

\n\n
SELECT\n  id,\n  (\n    SELECT\n      sub.val\n    FROM\n      test AS sub\n    WHERE\n      sub.id <= main.id\n      AND sub.val >= 5\n    ORDER BY\n      id DESC\n    LIMIT\n      1\n  ) AS val\nFROM\n  test AS main\nORDER BY\n  id ASC\n;\n
Run Code Online (Sandbox Code Playgroud)\n\n

这与 LAG() 类似,但更灵活(并且可能效率较低) \xe2\x80\x93 是一个经过调整的 LAG(),如果您愿意的话。

\n