Reputation: 1053
I need to find a simple way to turn an integer sequence in Biquery into a matrix with zeros on empty spaces
Example:
v1 v2 v3
5 2 1
needs to become
v1 v2 v3 v4 v5
5 2 1 0 0
0 5 2 1 0
0 0 5 2 1
etc.
I looked in all the possible places around but could not find how to do it in BQ or SQL.
Thanks
Upvotes: 1
Views: 682
Reputation: 173046
I would consider below solution to be generic enough
#standardSQL
WITH sequence AS (
SELECT ARRAY[5,2,1] AS num
),
numbers AS (
SELECT ARRAY_LENGTH(num) AS len,
ARRAY_CONCAT(num, ARRAY( SELECT 0 FROM sequence, UNNEST(num) AS x)) AS num
FROM sequence
)
SELECT
num[OFFSET(CASE WHEN 1 - n < 0 THEN 2 * len - n ELSE 1 - n END)],
num[OFFSET(CASE WHEN 2 - n < 0 THEN 2 * len - n ELSE 2 - n END)],
num[OFFSET(CASE WHEN 3 - n < 0 THEN 2 * len - n ELSE 3 - n END)],
num[OFFSET(CASE WHEN 4 - n < 0 THEN 2 * len - n ELSE 4 - n END)],
num[OFFSET(CASE WHEN 5 - n < 0 THEN 2 * len - n ELSE 5 - n END)]
FROM numbers, UNNEST(GENERATE_ARRAY(1, len)) AS n
ORDER BY n
You can easily adjust it to any sequence. For this you need to make changes in two places only:
adjust ARRAY values in sequence subquery (line 2)
add more rows like below into SELECT list
Row:
num[OFFSET(CASE WHEN Z - n < 0 THEN 2 * len - n ELSE Z - n END)]
you need to add as meny of such so that total number of the row will be 2xZ-1
and each next row has Z
incremented by 1
This can easily be script - so the whole query (or just SELECT list) will be generated for you then to run
If you are running this in client of your choice (python, go, etc.) - this can be part of your code so the whole stuff is automated
Upvotes: 2
Reputation: 11205
In its simplest form:
select v1, v2, v3, 0 as v4, 0 as v5
from MyTable
where (...)
union all
select 0, v1, v2, v3, 0
from MyTable
where (...)
union all
select 0,0,v1, v2, v3
from MyTable
where (...)
union all
select 0,0,0,v1, v2
from MyTable
where (...)
union all
select 0,0,0, 0,v1
from MyTable
where (...)
Upvotes: 0