如何在 Bigquery 中使用字段历史 table 重新创建旧快照
How to recreate old snapshot using field history table in Bigquery
我目前正在研究一个有趣的问题。我正在尝试重新创建 table 的状态,因为它是在给定的先前日期。我有 2 tables
- Table A:由实时数据组成,每小时刷新一次。
- Table A_field_history:包含对 Table A.
中字段所做的更改
下图包含当前状态,其中 Table A 具有实时更新数据,Table A_field_history 仅捕获对 table A 上的字段所做的更改。
我正在尝试重新创建特定给定日期的 Table A。下图包含 2020 年 6 月 30 日的 table 个状态。
要求是能够根据任何给定日期重新创建 Table A 的状态。
我实际上确定了一种方法来回滚(实际上,不是实际 table)在给定特定日期之后进行的所有更新。以下是遵循的步骤:
创建虚拟 tables:
WITH
Table_A AS
(
SELECT 1 As ID, '2020-6-28' as created_date, 10 as qty, 100 as value
Union ALL
SELECT 2 As ID, '2020-5-29' as created_date, 20 as qty, 200 as value),
Table_A_field_history AS
(
SELECT 'xyz' id,'2020-07-29' created_date,'12345' created_by,'qty' field,'10' new_value,'200' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-07-24' created_date,'12345' created_by,'qty' field,'20' new_value,'10' old_value,'2' A_id
UNION ALL
SELECT 'xyz' id,'2020-07-29' created_date,'12345' created_by,'value' field,'100' new_value,'2000' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-07-24' created_date,'12345' created_by,'value' field,'200' new_value,'5000' old_value,'2' A_id
UNION ALL
SELECT 'xyz' id,'2020-06-29' created_date,'12345' created_by,'qty' field,'200' new_value,'' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-05-30' created_date,'12345' created_by,'qty' field,'10' new_value,'' old_value,'2' A_id
UNION ALL
SELECT 'xyz' id,'2020-06-29' created_date,'12345' created_by,'value' field,'2000' new_value,'' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-05-30' created_date,'12345' created_by,'value' field,'5000' new_value,'' old_value,'2' A_id
),
第 1 步。创建日期 cte 以根据给定日期过滤数据:
`date_spine
AS
(
SELECT * FROM UNNEST(GENERATE_DATE_ARRAY('2020-01-01', CURRENT_DATE(), INTERVAL 1 Day)) AS as_of_date
),`
第 2 步。以上创建日期 cte 可用作我们查询的 Spine,交叉连接到地图 as_of_date
,其中包含历史记录中所做的所有更改 table。
date_changes
AS
(
SELECT DISTINCT
date.as_of_date,
hist.A_id
FROM Table_A_field_history hist CROSS JOIN date_spine date
),
第 3 步。现在我们已经 as_of_date
映射到所有历史交易,现在我们可以获得更改日期的最大值。
most_recent_changes AS (
SELECT
dc.as_of_date,
dc.A_id ,
MAX(fh.created_date) AS created_date,
FROM date_changes dc
LEFT JOIN Table_A_field_history AS fh
ON dc.A_id = fh.A_id
WHERE CAST(fh.created_date AS DATE) <= dc.as_of_date
GROUP BY dc.as_of_date,
dc.A_id
),
第 4 步。现在将最大更改日期映射到实际 created_date
和历史 table
past_changes AS (
SELECT
mr.as_of_date,
mr.A_id,
mr.created_date,
a.id AS entry_id,
a.created_by AS created_by_id,
CASE WHEN a.field='qty' THEN a.new_value ELSE '' END AS qty,
CASE WHEN a.field='value' THEN a.new_value ELSE '' END AS value,
FROM most_recent_changes AS mr
LEFT JOIN Table_A_field_history AS a
ON mr.A_id = a.A_id
AND mr.created_date = a.created_date
WHERE a.id IS NOT NULL
)
第 5 步。现在我们可以使用 as_of_date
获取 Table A 的历史状态。
Select *
From past_changes x
WHERE x.as_of_date = '2020-07-29'
我目前正在研究一个有趣的问题。我正在尝试重新创建 table 的状态,因为它是在给定的先前日期。我有 2 tables
- Table A:由实时数据组成,每小时刷新一次。
- Table A_field_history:包含对 Table A. 中字段所做的更改
下图包含当前状态,其中 Table A 具有实时更新数据,Table A_field_history 仅捕获对 table A 上的字段所做的更改。
我正在尝试重新创建特定给定日期的 Table A。下图包含 2020 年 6 月 30 日的 table 个状态。
要求是能够根据任何给定日期重新创建 Table A 的状态。
我实际上确定了一种方法来回滚(实际上,不是实际 table)在给定特定日期之后进行的所有更新。以下是遵循的步骤:
创建虚拟 tables:
WITH
Table_A AS
(
SELECT 1 As ID, '2020-6-28' as created_date, 10 as qty, 100 as value
Union ALL
SELECT 2 As ID, '2020-5-29' as created_date, 20 as qty, 200 as value),
Table_A_field_history AS
(
SELECT 'xyz' id,'2020-07-29' created_date,'12345' created_by,'qty' field,'10' new_value,'200' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-07-24' created_date,'12345' created_by,'qty' field,'20' new_value,'10' old_value,'2' A_id
UNION ALL
SELECT 'xyz' id,'2020-07-29' created_date,'12345' created_by,'value' field,'100' new_value,'2000' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-07-24' created_date,'12345' created_by,'value' field,'200' new_value,'5000' old_value,'2' A_id
UNION ALL
SELECT 'xyz' id,'2020-06-29' created_date,'12345' created_by,'qty' field,'200' new_value,'' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-05-30' created_date,'12345' created_by,'qty' field,'10' new_value,'' old_value,'2' A_id
UNION ALL
SELECT 'xyz' id,'2020-06-29' created_date,'12345' created_by,'value' field,'2000' new_value,'' old_value,'1' A_id
UNION ALL
SELECT 'abc' id,'2020-05-30' created_date,'12345' created_by,'value' field,'5000' new_value,'' old_value,'2' A_id
),
第 1 步。创建日期 cte 以根据给定日期过滤数据:
`date_spine
AS
(
SELECT * FROM UNNEST(GENERATE_DATE_ARRAY('2020-01-01', CURRENT_DATE(), INTERVAL 1 Day)) AS as_of_date
),`
第 2 步。以上创建日期 cte 可用作我们查询的 Spine,交叉连接到地图 as_of_date
,其中包含历史记录中所做的所有更改 table。
date_changes
AS
(
SELECT DISTINCT
date.as_of_date,
hist.A_id
FROM Table_A_field_history hist CROSS JOIN date_spine date
),
第 3 步。现在我们已经 as_of_date
映射到所有历史交易,现在我们可以获得更改日期的最大值。
most_recent_changes AS (
SELECT
dc.as_of_date,
dc.A_id ,
MAX(fh.created_date) AS created_date,
FROM date_changes dc
LEFT JOIN Table_A_field_history AS fh
ON dc.A_id = fh.A_id
WHERE CAST(fh.created_date AS DATE) <= dc.as_of_date
GROUP BY dc.as_of_date,
dc.A_id
),
第 4 步。现在将最大更改日期映射到实际 created_date
和历史 table
past_changes AS (
SELECT
mr.as_of_date,
mr.A_id,
mr.created_date,
a.id AS entry_id,
a.created_by AS created_by_id,
CASE WHEN a.field='qty' THEN a.new_value ELSE '' END AS qty,
CASE WHEN a.field='value' THEN a.new_value ELSE '' END AS value,
FROM most_recent_changes AS mr
LEFT JOIN Table_A_field_history AS a
ON mr.A_id = a.A_id
AND mr.created_date = a.created_date
WHERE a.id IS NOT NULL
)
第 5 步。现在我们可以使用 as_of_date
获取 Table A 的历史状态。
Select *
From past_changes x
WHERE x.as_of_date = '2020-07-29'