limit/top 的雪花查询条件

Snowflake query for limit/top with condition

Snowflake 中,我试图根据条件限制行数。查询是从应用程序生成的。

我试图实现的逻辑。

让我们考虑 a 作为行数计数,如果它是 -1 那么我想检索所有行。

SELECT * FROM "PUBLIC".TABLE1 LIMIT ( 
CASE WHEN a = -1
THEN
  -- no limit
ELSE 
 a

a会被应用解析为数字。这种操作在Snowflake中可以吗?

Above query is not working in Snowflake, just added it to specify the requirement

我认为您可以使用 ROW_NUMBER and QUALIFY 函数来实现:

WITH sample_data AS (
  SELECT SEQ4()+1 AS val, 100 AS a
    FROM TABLE(GENERATOR(ROWCOUNT => 1000)) AS t
)
SELECT ROW_NUMBER() OVER(ORDER BY val) AS rn
  FROM sample_data
QUALIFY rn <= IFF(a = -1, rn, a);

结果:100 rows

WITH sample_data AS (
  SELECT SEQ4()+1 AS val, -1 AS a
    FROM TABLE(GENERATOR(ROWCOUNT => 1000)) AS t
)
SELECT ROW_NUMBER() OVER(ORDER BY val) AS rn
  FROM sample_data
QUALIFY rn <= IFF(a = -1, rn, a);

结果:1000 rows -- 没有限制,所有行

您可以使用 SQL Procedure(在 public 预览中):

create or replace table test (a int);
insert into test values (1), (2), (3), (4), (5);
select * from test;

create or replace procedure dynamic_limit(limit int)
returns table(a int)
language sql
as
$$
    declare
        query string default 'SELECT * FROM TEST'; 
    begin
        IF (limit > 0) THEN
            query := :query || ' LIMIT ' || :limit;
        END IF;
    
        let res resultset default (execute immediate :query);
        return table(res);
    end;
$$;

call dynamic_limit(-1);
+---+
| A |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+---+

call dynamic_limit(0);
+---+
| A |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+---+

call dynamic_limit(1);
+---+
| A |
|---|
| 1 |
+---+

call dynamic_limit(4);
+---+
| A |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
+---+

Michael 的回答很好,我把它翻转成一个会话变量,这样就有一点独立性了

SET A = 5;
/* session variable to "control" */

WITH sample_data AS (
  SELECT
    SEQ4() AS val
  FROM TABLE(GENERATOR(ROWCOUNT => 1000))
)
/* CTE for data */

SELECT *
    ,ROW_NUMBER() OVER(ORDER BY val) AS RN
FROM sample_data
QUALIFY RN <= IFF($a = -1, rn, $a);
VAL RN
0 1
1 2
2 3
3 4
4 5

然而,我们可以通过取反 ROW_NUMBER 的符号和一些符号翻转将 ROW_NUMBER 移动到 QUALIFY 中,因此不需要知道当前行数或最大行数 rn 我们可以比较零:

SELECT sd.*
FROM sample_data AS sd
QUALIFY ($a - ROW_NUMBER() OVER(ORDER BY sd.val)) * $a >= 0;
VAL
0
1
2
3
4

这是有效的,因为我们的行号从 -1 -> -infinity 开始,但我们从一个限制(-1 或 5)中获取它,然后将其乘以限制,对于负值,将符号翻转为所有正数,对于正数限制,对正值的数量没有任何影响

可以在这段工作代码中看到:

SELECT *
   ,ROW_NUMBER() OVER(ORDER BY val) as rn
   ,(5 - rn) * 5
   ,(-1 - rn) * -1
FROM sample_data

显示 5 或 -1 的数学运算结果

VAL RN (5 - RN) * 5 (-1 - RN) * -1
0 1 20 2
1 2 15 3
2 3 10 4
3 4 5 5
4 5 0 6
5 6 -5 7
6 7 -10 8
7 8 -15 9
8 9 -20 10
9 10 -25 11