limit/top 的雪花查询条件
Snowflake query for limit/top with condition
在 Snowflake
中,我试图根据条件限制行数。查询是从应用程序生成的。
我试图实现的逻辑。
- 如果条件匹配,则 select table
中的所有行
- else 限制给定的行号
让我们考虑 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
在 Snowflake
中,我试图根据条件限制行数。查询是从应用程序生成的。
我试图实现的逻辑。
- 如果条件匹配,则 select table 中的所有行
- else 限制给定的行号
让我们考虑 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 |