我有一个这样的简化表:
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)
我认为 LAG() 不能在这里使用,因为使用 LAG,您需要具体说明要返回多少行。(默认情况下为 1,但您可以指定 3、10 或任何其他数字。但重点是它必须是特定数字。)在您的情况下,您不知道最后一个匹配值是否在上一行或之前的行,甚至更早。
\n\n因此,另一种方法是查找具有匹配值的最后一行的 ID,然后查找该 ID 以获取最终输出 \xe2\x80\x93 的值,如下所示:
\n\nSELECT\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;\nRun Code Online (Sandbox Code Playgroud)\n\n或者,您可以使用相关子查询来获取从最低 ID 到当前 ID 的子集中最后一个大于 5 的值:
\n\nSELECT\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;\nRun Code Online (Sandbox Code Playgroud)\n\n这与 LAG() 类似,但更灵活(并且可能效率较低) \xe2\x80\x93 是一个经过调整的 LAG(),如果您愿意的话。
\n