# 自定义滚动计算

##### 问题描述投票：0回答：1

``````A(t) = {
WHEN B(t-1) < 10 : B(t-1)
WHEN B(t-1) >=10 : B(t-1) / 6
}

B(t) = A(t) * 2
``````

``````SELECT * FROM model ORDER BY t;
``````
``````| t | A    | B    |
|---|------|------|
| 0 | 0    | 9    |
| 1 | null | null |
| 2 | null | null |
| 3 | null | null |
| 4 | null | null |
``````

``````| t | A | B  |
|---|---|----|
| 0 | 0 | 9  |
| 1 | 9 | 18 |
| 2 | 3 | 6  |
| 3 | 6 | 12 |
| 4 | 2 | 4  |
``````

``````CREATE TEMPORARY FUNCTION A_fn(b_prev FLOAT64) AS (
CASE
WHEN b_prev < 10 THEN b_prev
ELSE b_prev / 6.0
END
);

SELECT
t,
CASE WHEN t = 0 THEN A ELSE A_fn(LAG(B) OVER (ORDER BY t)) END AS A,
CASE WHEN t = 0 THEN B ELSE A_fn(LAG(B) OVER (ORDER BY t)) * 2 END AS B
FROM model
ORDER BY t;
``````

``````| t | A    | B    |
|---|------|------|
| 0 | 0    | 9    |
| 1 | 9    | 18   |
| 2 | null | null |
| 3 | null | null |
| 4 | null | null |
``````

google-bigquery
##### 1个回答
1

``````#standardSQL
CREATE TEMP FUNCTION x(v FLOAT64, t INT64)
RETURNS ARRAY<STRUCT<t INT64, v FLOAT64>>
LANGUAGE js AS """
var i, result = [];
for (i = 1; i <= t; i++) {
if (v < 10) {v = 2 * v}
else {v = v / 3};
result.push({t:i, v});
};
return result
""";
SELECT 0 AS t, 0 AS A, 9 AS B UNION ALL
SELECT line.t, line.v / 2, line.v FROM UNNEST(x(9, 3000000)) line
``````

``````#standardSQL
CREATE TEMP FUNCTION anchor(seed FLOAT64, len INT64, batch INT64)
RETURNS ARRAY<STRUCT<t INT64, v FLOAT64>> LANGUAGE js AS """
var i, result = [], v = seed;
for (i = 0; i <= len; i++) {
if (v < 10) {v = 2 * v} else {v = v / 3};
if (i % batch == 0) {result.push({t:i + 1, v})};
}; return result
""";
CREATE TEMP FUNCTION x(value FLOAT64, start INT64, len INT64)
RETURNS ARRAY<STRUCT<t INT64, v FLOAT64>>
LANGUAGE js AS """
var i, result = []; result.push({t:0, v:value});
for (i = 1; i < len; i++) {
if (value < 10) {value = 2 * value} else {value = value / 3};
result.push({t:i, v:value});
}; return result
""";
CREATE OR REPLACE TABLE `project.dataset.result` AS
WITH settings AS (SELECT 9 init, 2000000000 len, 1000 batch),
anchors  AS (SELECT line.* FROM settings, UNNEST(anchor(init, len, batch)) line)
SELECT 0 AS t, 0 AS A, init AS B FROM settings UNION ALL
SELECT a.t + line.t, line.v / 2, line.v
FROM settings, anchors a, UNNEST(x(v, t, batch)) line
``````

``````WITH settings AS (SELECT 9 init, 2000000000 len, 1000 batch),
``````

``````  1M: SELECT 9 init,    1000000 len,  1000 batch  -  0 min  9 sec
10M: SELECT 9 init,   10000000 len,  1000 batch  -  0 min 50 sec
100M: SELECT 9 init,  100000000 len,   600 batch  -  3 min  4 sec
100M: SELECT 9 init,  100000000 len,    40 batch  -  2 min 56 sec
1B: SELECT 9 init, 1000000000 len, 10000 batch  - 29 min 39 sec
1B: SELECT 9 init, 1000000000 len,  1000 batch  - 27 min 50 sec
2B: SELECT 9 init, 2000000000 len,  1000 batch  - 48 min 27 sec
``````