Files
greptimedb/tests/cases/standalone/common/promql/scalar.result
Ruihang Xia 59dd418629 feat: simplify nested aggr inside count query (#7859)
* as optimizer rule

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* dump changes

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* perf: tighten count-count optimizer rewrite

* extend inner op set

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* simplify and more coverage

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* remove prom-non-null

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* preserve value column through pruning

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* more sqlness cases

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* rename

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* enforce is not null before inner aggr

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* finalize

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

* update sqlness result

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>

---------

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
2026-03-26 00:08:38 +00:00

651 lines
29 KiB
Plaintext

CREATE TABLE host (
ts timestamp(3) time index,
host STRING PRIMARY KEY,
val BIGINT,
);
Affected Rows: 0
INSERT INTO TABLE host VALUES
(0, 'host1', 1),
(0, 'host2', 2),
(5000, 'host1', 3),
(5000, 'host2', 4),
(10000, 'host1', 5),
(10000, 'host2', 6),
(15000, 'host1', 7),
(15000, 'host2', 8);
Affected Rows: 8
-- case only have one time series, scalar return value
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host{host="host1"});
+---------------------+-------------+
| ts | scalar(val) |
+---------------------+-------------+
| 1970-01-01T00:00:00 | 1.0 |
| 1970-01-01T00:00:05 | 3.0 |
| 1970-01-01T00:00:10 | 5.0 |
| 1970-01-01T00:00:15 | 7.0 |
+---------------------+-------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host{host="host1"}) + 1;
+---------------------+--------------------------+
| ts | scalar(val) + Float64(1) |
+---------------------+--------------------------+
| 1970-01-01T00:00:00 | 2.0 |
| 1970-01-01T00:00:05 | 4.0 |
| 1970-01-01T00:00:10 | 6.0 |
| 1970-01-01T00:00:15 | 8.0 |
+---------------------+--------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') 1 + scalar(host{host="host1"});
+---------------------+--------------------------+
| ts | Float64(1) + scalar(val) |
+---------------------+--------------------------+
| 1970-01-01T00:00:00 | 2.0 |
| 1970-01-01T00:00:05 | 4.0 |
| 1970-01-01T00:00:10 | 6.0 |
| 1970-01-01T00:00:15 | 8.0 |
+---------------------+--------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host{host="host1"}) + scalar(host{host="host2"});
+---------------------+-----------------------------------+
| ts | lhs.scalar(val) + rhs.scalar(val) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:00 | 3.0 |
| 1970-01-01T00:00:05 | 7.0 |
| 1970-01-01T00:00:10 | 11.0 |
| 1970-01-01T00:00:15 | 15.0 |
+---------------------+-----------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') host{host="host1"} + scalar(host{host="host2"});
+-------+---------------------+---------------------------+
| host | ts | lhs.val + rhs.scalar(val) |
+-------+---------------------+---------------------------+
| host1 | 1970-01-01T00:00:00 | 3.0 |
| host1 | 1970-01-01T00:00:05 | 7.0 |
| host1 | 1970-01-01T00:00:10 | 11.0 |
| host1 | 1970-01-01T00:00:15 | 15.0 |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host{host="host1"}) + host{host="host2"};
+-------+---------------------+---------------------------+
| host | ts | lhs.scalar(val) + rhs.val |
+-------+---------------------+---------------------------+
| host2 | 1970-01-01T00:00:00 | 3.0 |
| host2 | 1970-01-01T00:00:05 | 7.0 |
| host2 | 1970-01-01T00:00:10 | 11.0 |
| host2 | 1970-01-01T00:00:15 | 15.0 |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') host + scalar(host{host="host2"});
+-------+---------------------+---------------------------+
| host | ts | lhs.val + rhs.scalar(val) |
+-------+---------------------+---------------------------+
| host1 | 1970-01-01T00:00:00 | 3.0 |
| host1 | 1970-01-01T00:00:05 | 7.0 |
| host1 | 1970-01-01T00:00:10 | 11.0 |
| host1 | 1970-01-01T00:00:15 | 15.0 |
| host2 | 1970-01-01T00:00:00 | 4.0 |
| host2 | 1970-01-01T00:00:05 | 8.0 |
| host2 | 1970-01-01T00:00:10 | 12.0 |
| host2 | 1970-01-01T00:00:15 | 16.0 |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host{host="host1"}) + host;
+-------+---------------------+---------------------------+
| host | ts | lhs.scalar(val) + rhs.val |
+-------+---------------------+---------------------------+
| host1 | 1970-01-01T00:00:00 | 2.0 |
| host1 | 1970-01-01T00:00:05 | 6.0 |
| host1 | 1970-01-01T00:00:10 | 10.0 |
| host1 | 1970-01-01T00:00:15 | 14.0 |
| host2 | 1970-01-01T00:00:00 | 3.0 |
| host2 | 1970-01-01T00:00:05 | 7.0 |
| host2 | 1970-01-01T00:00:10 | 11.0 |
| host2 | 1970-01-01T00:00:15 | 15.0 |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(count(count(host) by (host)));
+---------------------+--------------------------------+
| ts | scalar(count(count(host.val))) |
+---------------------+--------------------------------+
| 1970-01-01T00:00:00 | 2.0 |
| 1970-01-01T00:00:05 | 2.0 |
| 1970-01-01T00:00:10 | 2.0 |
| 1970-01-01T00:00:15 | 2.0 |
+---------------------+--------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(count(sum(host) by (host)));
+---------------------+------------------------------+
| ts | scalar(count(sum(host.val))) |
+---------------------+------------------------------+
| 1970-01-01T00:00:00 | 2.0 |
| 1970-01-01T00:00:05 | 2.0 |
| 1970-01-01T00:00:10 | 2.0 |
| 1970-01-01T00:00:15 | 2.0 |
+---------------------+------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(count(avg(host) by (host)));
+---------------------+------------------------------+
| ts | scalar(count(avg(host.val))) |
+---------------------+------------------------------+
| 1970-01-01T00:00:00 | 2.0 |
| 1970-01-01T00:00:05 | 2.0 |
| 1970-01-01T00:00:10 | 2.0 |
| 1970-01-01T00:00:15 | 2.0 |
+---------------------+------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(count(stddev(host) by (host)));
+---------------------+-------------------------------------+
| ts | scalar(count(stddev_pop(host.val))) |
+---------------------+-------------------------------------+
| 1970-01-01T00:00:00 | 2.0 |
| 1970-01-01T00:00:05 | 2.0 |
| 1970-01-01T00:00:10 | 2.0 |
| 1970-01-01T00:00:15 | 2.0 |
+---------------------+-------------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host{host="host1"} + scalar(host{host="host2"}));
+---------------------+-----------------------------------+
| ts | scalar(lhs.val + rhs.scalar(val)) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:00 | 3.0 |
| 1970-01-01T00:00:05 | 7.0 |
| 1970-01-01T00:00:10 | 11.0 |
| 1970-01-01T00:00:15 | 15.0 |
+---------------------+-----------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(scalar(host{host="host2"}) + host{host="host1"});
+---------------------+-----------------------------------+
| ts | scalar(lhs.scalar(val) + rhs.val) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:00 | 3.0 |
| 1970-01-01T00:00:05 | 7.0 |
| 1970-01-01T00:00:10 | 11.0 |
| 1970-01-01T00:00:15 | 15.0 |
+---------------------+-----------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host + scalar(host{host="host2"}));
+---------------------+-----------------------------------+
| ts | scalar(lhs.val + rhs.scalar(val)) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:00:05 | NaN |
| 1970-01-01T00:00:10 | NaN |
| 1970-01-01T00:00:15 | NaN |
+---------------------+-----------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(scalar(host{host="host2"}) + host);
+---------------------+-----------------------------------+
| ts | scalar(lhs.scalar(val) + rhs.val) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:00:05 | NaN |
| 1970-01-01T00:00:10 | NaN |
| 1970-01-01T00:00:15 | NaN |
+---------------------+-----------------------------------+
-- case have multiple time series, scalar return NaN
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host);
+---------------------+-------------+
| ts | scalar(val) |
+---------------------+-------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:00:05 | NaN |
| 1970-01-01T00:00:10 | NaN |
| 1970-01-01T00:00:15 | NaN |
+---------------------+-------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host) + 1;
+---------------------+--------------------------+
| ts | scalar(val) + Float64(1) |
+---------------------+--------------------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:00:05 | NaN |
| 1970-01-01T00:00:10 | NaN |
| 1970-01-01T00:00:15 | NaN |
+---------------------+--------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') 1 + scalar(host);
+---------------------+--------------------------+
| ts | Float64(1) + scalar(val) |
+---------------------+--------------------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:00:05 | NaN |
| 1970-01-01T00:00:10 | NaN |
| 1970-01-01T00:00:15 | NaN |
+---------------------+--------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host) + scalar(host);
+---------------------+-----------------------------------+
| ts | lhs.scalar(val) + rhs.scalar(val) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:00:05 | NaN |
| 1970-01-01T00:00:10 | NaN |
| 1970-01-01T00:00:15 | NaN |
+---------------------+-----------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') host + scalar(host);
+-------+---------------------+---------------------------+
| host | ts | lhs.val + rhs.scalar(val) |
+-------+---------------------+---------------------------+
| host1 | 1970-01-01T00:00:00 | NaN |
| host1 | 1970-01-01T00:00:05 | NaN |
| host1 | 1970-01-01T00:00:10 | NaN |
| host1 | 1970-01-01T00:00:15 | NaN |
| host2 | 1970-01-01T00:00:00 | NaN |
| host2 | 1970-01-01T00:00:05 | NaN |
| host2 | 1970-01-01T00:00:10 | NaN |
| host2 | 1970-01-01T00:00:15 | NaN |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host) + host;
+-------+---------------------+---------------------------+
| host | ts | lhs.scalar(val) + rhs.val |
+-------+---------------------+---------------------------+
| host1 | 1970-01-01T00:00:00 | NaN |
| host1 | 1970-01-01T00:00:05 | NaN |
| host1 | 1970-01-01T00:00:10 | NaN |
| host1 | 1970-01-01T00:00:15 | NaN |
| host2 | 1970-01-01T00:00:00 | NaN |
| host2 | 1970-01-01T00:00:05 | NaN |
| host2 | 1970-01-01T00:00:10 | NaN |
| host2 | 1970-01-01T00:00:15 | NaN |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') host{host="host2"} + scalar(host);
+-------+---------------------+---------------------------+
| host | ts | lhs.val + rhs.scalar(val) |
+-------+---------------------+---------------------------+
| host2 | 1970-01-01T00:00:00 | NaN |
| host2 | 1970-01-01T00:00:05 | NaN |
| host2 | 1970-01-01T00:00:10 | NaN |
| host2 | 1970-01-01T00:00:15 | NaN |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host) + host{host="host2"};
+-------+---------------------+---------------------------+
| host | ts | lhs.scalar(val) + rhs.val |
+-------+---------------------+---------------------------+
| host2 | 1970-01-01T00:00:00 | NaN |
| host2 | 1970-01-01T00:00:05 | NaN |
| host2 | 1970-01-01T00:00:10 | NaN |
| host2 | 1970-01-01T00:00:15 | NaN |
+-------+---------------------+---------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(host{host="host1"} + scalar(host));
+---------------------+-----------------------------------+
| ts | scalar(lhs.val + rhs.scalar(val)) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:00:05 | NaN |
| 1970-01-01T00:00:10 | NaN |
| 1970-01-01T00:00:15 | NaN |
+---------------------+-----------------------------------+
-- No data input in scalar
TQL EVAL (350, 360, '5s') scalar(host{host="host1"});
+---------------------+-------------+
| ts | scalar(val) |
+---------------------+-------------+
| 1970-01-01T00:05:50 | NaN |
| 1970-01-01T00:05:55 | NaN |
| 1970-01-01T00:06:00 | NaN |
+---------------------+-------------+
DELETE from host where ts = 0;
Affected Rows: 2
-- Under this case, InstantManipulate will input a valid record batch but output a empty record batch (because no data will be selected in this batch)
-- Test input a empty record batch to ScalarCalculate plan
TQL EVAL (0, 1600, '6m40s') scalar(host{host="host1"});
+---------------------+-------------+
| ts | scalar(val) |
+---------------------+-------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:06:40 | NaN |
| 1970-01-01T00:13:20 | NaN |
| 1970-01-01T00:20:00 | NaN |
| 1970-01-01T00:26:40 | NaN |
+---------------------+-------------+
-- error case
TQL EVAL (0, 15, '5s') scalar(1 + scalar(host{host="host2"}));
Error: 2000(InvalidSyntax), expected type vector in call to function 'scalar', got scalar
TQL EVAL (0, 15, '5s') scalar(scalar(host{host="host2"}) + 1);
Error: 2000(InvalidSyntax), expected type vector in call to function 'scalar', got scalar
TQL EVAL (0, 15, '5s') scalar(scalar(host{host="host1"}) + scalar(host{host="host2"}));
Error: 2000(InvalidSyntax), expected type vector in call to function 'scalar', got scalar
-- Test clamp functions with vector input and scalar bounds
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp(host, 0, 12);
+---------------------+-----------------------------------+-------+
| ts | clamp(val,Float64(0),Float64(12)) | host |
+---------------------+-----------------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:05 | 4.0 | host2 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:10 | 6.0 | host2 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
| 1970-01-01T00:00:15 | 8.0 | host2 |
+---------------------+-----------------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp(host, 6 - 6, 6 + 6);
+---------------------+------------------------------------------------------------+-------+
| ts | clamp(val,Float64(6) - Float64(6),Float64(6) + Float64(6)) | host |
+---------------------+------------------------------------------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:05 | 4.0 | host2 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:10 | 6.0 | host2 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
| 1970-01-01T00:00:15 | 8.0 | host2 |
+---------------------+------------------------------------------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp(host, 12, 0);
Error: 3001(EngineExecuteQuery), Execution error: min '12' > max '0'
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp(host{host="host1"}, -1, 6);
+---------------------+-----------------------------------+-------+
| ts | clamp(val,Float64(-1),Float64(6)) | host |
+---------------------+-----------------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:15 | 6.0 | host1 |
+---------------------+-----------------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp_min(host{host="host1"}, 10);
+---------------------+----------------------------+-------+
| ts | clamp_min(val,Float64(10)) | host |
+---------------------+----------------------------+-------+
| 1970-01-01T00:00:05 | 10.0 | host1 |
| 1970-01-01T00:00:10 | 10.0 | host1 |
| 1970-01-01T00:00:15 | 10.0 | host1 |
+---------------------+----------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp_min(host{host="host1"}, 1);
+---------------------+---------------------------+-------+
| ts | clamp_min(val,Float64(1)) | host |
+---------------------+---------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
+---------------------+---------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp_max(host{host="host1"}, 1);
+---------------------+---------------------------+-------+
| ts | clamp_max(val,Float64(1)) | host |
+---------------------+---------------------------+-------+
| 1970-01-01T00:00:05 | 1.0 | host1 |
| 1970-01-01T00:00:10 | 1.0 | host1 |
| 1970-01-01T00:00:15 | 1.0 | host1 |
+---------------------+---------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp_max(host{host="host1"}, 10);
+---------------------+----------------------------+-------+
| ts | clamp_max(val,Float64(10)) | host |
+---------------------+----------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
+---------------------+----------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp_min(host, 1);
+---------------------+---------------------------+-------+
| ts | clamp_min(val,Float64(1)) | host |
+---------------------+---------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:05 | 4.0 | host2 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:10 | 6.0 | host2 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
| 1970-01-01T00:00:15 | 8.0 | host2 |
+---------------------+---------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp_max(host, 10);
+---------------------+----------------------------+-------+
| ts | clamp_max(val,Float64(10)) | host |
+---------------------+----------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:05 | 4.0 | host2 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:10 | 6.0 | host2 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
| 1970-01-01T00:00:15 | 8.0 | host2 |
+---------------------+----------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(clamp(host{host="host1"}, 0, 6));
+---------------------+------------------------------------------+
| ts | scalar(clamp(val,Float64(0),Float64(6))) |
+---------------------+------------------------------------------+
| 1970-01-01T00:00:05 | 3.0 |
| 1970-01-01T00:00:10 | 5.0 |
| 1970-01-01T00:00:15 | 6.0 |
+---------------------+------------------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(clamp_min(host{host="host1"}, 1));
+---------------------+-----------------------------------+
| ts | scalar(clamp_min(val,Float64(1))) |
+---------------------+-----------------------------------+
| 1970-01-01T00:00:05 | 3.0 |
| 1970-01-01T00:00:10 | 5.0 |
| 1970-01-01T00:00:15 | 7.0 |
+---------------------+-----------------------------------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') scalar(clamp_max(host{host="host1"}, 10));
+---------------------+------------------------------------+
| ts | scalar(clamp_max(val,Float64(10))) |
+---------------------+------------------------------------+
| 1970-01-01T00:00:05 | 3.0 |
| 1970-01-01T00:00:10 | 5.0 |
| 1970-01-01T00:00:15 | 7.0 |
+---------------------+------------------------------------+
-- Test nested clamp functions
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp(clamp_min(host{host="host1"}, 1), 0, 12);
+---------------------+---------------------------------------------------------+-------+
| ts | clamp(clamp_min(val,Float64(1)),Float64(0),Float64(12)) | host |
+---------------------+---------------------------------------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
+---------------------+---------------------------------------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 15, '5s') clamp_max(clamp(host{host="host1"}, 0, 15), 6);
+---------------------+---------------------------------------------------------+-------+
| ts | clamp_max(clamp(val,Float64(0),Float64(15)),Float64(6)) | host |
+---------------------+---------------------------------------------------------+-------+
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:15 | 6.0 | host1 |
+---------------------+---------------------------------------------------------+-------+
DROP TABLE host;
Affected Rows: 0
CREATE TABLE presence_metric (
ts timestamp(3) time index,
instance STRING,
cpu STRING,
shard STRING,
val DOUBLE,
PRIMARY KEY (instance, cpu, shard),
);
Affected Rows: 0
INSERT INTO TABLE presence_metric VALUES
(0, 'i1', 'cpu0', 'a', 1.0),
(0, 'i1', 'cpu0', 'b', 2.0),
(0, 'i1', 'cpu1', 'a', 10.0),
(0, 'i1', 'cpu2', 'a', 20.0),
(0, 'i2', 'cpu9', 'a', 100.0),
(200000, 'i1', 'cpu0', 'a', 'NAN'::DOUBLE),
(200000, 'i1', 'cpu0', 'b', 'NAN'::DOUBLE),
(200000, 'i1', 'cpu1', 'a', 11.0),
(200000, 'i1', 'cpu2', 'a', NULL),
(200000, 'i2', 'cpu9', 'a', 101.0),
(400000, 'i1', 'cpu1', 'a', 12.0),
(400000, 'i2', 'cpu9', 'a', 102.0),
(600000, 'i1', 'cpu0', 'a', 7.0),
(600000, 'i1', 'cpu0', 'b', 8.0),
(600000, 'i2', 'cpu9', 'a', 103.0);
Affected Rows: 15
-- NaN drops `cpu0` from the grouped count, while the NULL sample on `cpu2`
-- still leaves a zero-valued row in `count(...) by (cpu)`.
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 600, '200s') count(presence_metric{instance="i1"}) by (cpu);
+------+---------------------+----------------------------+
| cpu | ts | count(presence_metric.val) |
+------+---------------------+----------------------------+
| cpu0 | 1970-01-01T00:00:00 | 2 |
| cpu0 | 1970-01-01T00:10:00 | 2 |
| cpu1 | 1970-01-01T00:00:00 | 1 |
| cpu1 | 1970-01-01T00:03:20 | 1 |
| cpu1 | 1970-01-01T00:06:40 | 1 |
| cpu1 | 1970-01-01T00:10:00 | 1 |
| cpu2 | 1970-01-01T00:00:00 | 1 |
| cpu2 | 1970-01-01T00:03:20 | 0 |
| cpu2 | 1970-01-01T00:06:40 | 0 |
+------+---------------------+----------------------------+
-- Nested-count rewrite should preserve grouped presence after stale-NaN filtering and null-value pruning.
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 600, '200s') scalar(count(count(presence_metric{instance="i1"}) by (cpu)));
+---------------------+-------------------------------------------+
| ts | scalar(count(count(presence_metric.val))) |
+---------------------+-------------------------------------------+
| 1970-01-01T00:00:00 | 3.0 |
| 1970-01-01T00:03:20 | 2.0 |
| 1970-01-01T00:06:40 | 2.0 |
| 1970-01-01T00:10:00 | 2.0 |
+---------------------+-------------------------------------------+
-- Non-count inner aggregates must drop NULL-only groups before the outer count.
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 600, '200s') scalar(count(sum(presence_metric{instance="i1"}) by (cpu)));
+---------------------+-----------------------------------------+
| ts | scalar(count(sum(presence_metric.val))) |
+---------------------+-----------------------------------------+
| 1970-01-01T00:00:00 | 3.0 |
| 1970-01-01T00:03:20 | 1.0 |
| 1970-01-01T00:06:40 | 1.0 |
| 1970-01-01T00:10:00 | 2.0 |
+---------------------+-----------------------------------------+
-- False case: outer `by (instance)` keeps multiple series at the scalar input, so scalar should still yield NaN.
-- SQLNESS SORT_RESULT 3 1
TQL EVAL (0, 600, '200s') scalar(count(count(presence_metric) by (instance, cpu)) by (instance));
+---------------------+-------------------------------------------+
| ts | scalar(count(count(presence_metric.val))) |
+---------------------+-------------------------------------------+
| 1970-01-01T00:00:00 | NaN |
| 1970-01-01T00:03:20 | NaN |
| 1970-01-01T00:06:40 | NaN |
| 1970-01-01T00:10:00 | NaN |
+---------------------+-------------------------------------------+
DROP TABLE presence_metric;
Affected Rows: 0