ã¯ããã« dbt snapshotãšã¯ïŒãã£ããïŒ ä»åã®äŸ å
šäœã®æµã snapshotå
éšåŠçã®è©³çް deleteåŠçïŒå®å
ããŒãã«ã«ååšããã¬ã³ãŒãããœãŒã¹ããŒãã«ã§deleteãããŠããå Žå updateåŠçïŒå®å
ããŒãã«ãšæ¯èŒããŠãœãŒã¹ããŒãã«ã®ã¬ã³ãŒããupdateãããŠããå Žå insertåŠçïŒå®å
ããŒãã«ã«ç¡ãã¬ã³ãŒãããœãŒã¹ããŒãã«åŽã«æ°èŠã§äœæãããŠããå Žå checkæŠç¥ã®å Žå checkæŠç¥ã®è©³çް ãŸãšã Weâre Hired ã¯ããã« ããã«ã¡ã¯âïžokodooooonã§ã æè¿ã瀟å
ã®dbt snapshotã¢ãã«ã§ããã©ãŒãã³ã¹ã®åé¡ãçºçãããã®è§£æ±ºã«èŠåŽããŸãããdbt snapshotã®å
éšåŠçãå
¬åŒããã¥ã¡ã³ããªã©ã§æç€ºãããŠãããã詳现ãªã¯ãšãªãçè§£ããŠããªãã£ãããã§ãã ããã§ãä»åãdbt snapshotã®å
éšã¯ãšãªã«ã€ããŠè§£èª¬ããŠã¿ãããšã«ããŸããããã ããä»åã®è§£èª¬å
容ã¯ãããã¥ã¡ã³ãã§èª¬æãããŠããéãã®æåãã©ã®ããã«SQLã§è¡šçŸãããŠããã®ã確èªãããã®ã§ãæ°ããçºèŠãTipsã¿ãããªãã®ã¯ç¹ã«ãªãã§ãïŒ å
éšåŠçããã£ããçè§£ããããšã§ãdbtã«ãã£ãŠæœè±¡åãããåŠçããã广çã«æŽ»çšã§ããããšãããããªããšæã£ãŠãããŸãã®ã§ãã©ãªããã®åèã«ãªãã°å¹žãã§ãïŒ ïŒä»å解説ããã¯ãšãªã¯ãdbt-bigqueryã§çæãããã¯ãšãªã§ãïŒ dbt snapshotãšã¯ïŒãã£ããïŒ SCD Type2 Dimensionãšããææ³ã«åŸã£ãŠãé廿ç¹ã®ç¶æ
ã®é·ç§»ãèç©ã§ãããããªä»çµã¿ã§ãã ãœãŒã¹ã·ã¹ãã åŽã§ã¯ã¹ããŒã¿ã¹å€æŽãè¡ããããšããã®ããã¥ã©ã«ããŒã®ã¬ã³ãŒããäžæžãåŠçãããŸããããã®äžæžãåŠçååŸã®ã¬ã³ãŒããããããæå¹æéä»ãã§ä¿åããŸã å
¬åŒDoc: https://docs.getdbt.com/docs/build/snapshots ä»åã®äŸ 以äžã®ãããªã¢ãã«ãä»®å®ããŠãsnapshotã®ã¯ãšãªãèŠãŠãããããšæããŸãã ã¢ãã«ãã¡ã€ã«äžã®å®çŸ©ã¯ãããªæãã§ãã {% snapshot snapshotted_sample_table %} {{ config( target_schema= ' sample_dataset ' , strategy= ' timestamp ' , unique_key= ' id ' , updated_at= ' updated_at ' , invalidate_hard_deletes= True , ) }} select * from {{ source( ' sample_dataset ' , ' sample_data ' ) }} {% endsnapshot %} ãœãŒã¹ããŒãã«åŽã§äžæã§ããã«ã©ã ãunique_key, ã¬ã³ãŒãæŽæ°æ¥æãèšé²ããã«ã©ã ãupdated_atã«æå®ããŠããŸãã å·Šã®ããŒãã«ãsnapshotåãããããšã§ãå³ã®ããã«æå¹æé(dbt_valid_from, dbt_valid_to)ãšsnapshotåŸã®ã¬ã³ãŒãã«å¯ŸãããŠããŒã¯ããŒ(dbt_scd_id)ãä»äžãããŸã å
šäœã®æµã dbt snapshotã¯BigQueryã«ãããŠïŒã€ã®ã¯ãšãªãå®è¡ããŠããŸãã ãœãŒã¹ããŒãã«ãšå®å
ããŒãã«ããããŒã¿ãæœåºããŠãsnapshotå
ã«mergeããããã®tmpããŒãã«ããupdate,delete,insertããããã®åŠçããšã«åå²ããŠäœæããåŠç tmpããŒãã«ã§ã©ããªã³ã°ãããåŠçããšã«MERGEã¯ãšãªãå®è¡ããåŠç ããããå®è¡ãããã¯ãšãªã®è©³çްã¯ä»¥äžã®ããã«ãªããŸãã tmpããŒãã«äœæã¯ãšãªå
šæã ïŒã¯ãªãã¯ã§å±éïŒ ```sql create or replace table `sample_project`.`sample_dataset`.`sample_table__dbt_tmp` OPTIONS( description="""""", expiration_timestamp=TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 12 hour) ) as ( with snapshot_query as ( SELECT * FROM `sample_project`.`sample_dataset`.`sample_table` ), snapshotted_data as ( select *, id as dbt_unique_key from `sample_project`.`sample_dataset`.`snapshotted_sample_table` where dbt_valid_to is null ), insertions_source_data as ( select *, id as dbt_unique_key, updated_at as dbt_updated_at, updated_at as dbt_valid_from, nullif(updated_at, updated_at) as dbt_valid_to, to_hex(md5(concat(coalesce(cast(id as string), ''), '|',coalesce(cast(updated_at as string), '')))) as dbt_scd_id from snapshot_query ), updates_source_data as ( select *, id as dbt_unique_key, updated_at as dbt_updated_at, updated_at as dbt_valid_from, updated_at as dbt_valid_to from snapshot_query ), deletes_source_data as ( select *, id as dbt_unique_key from snapshot_query ), insertions as ( select 'insert' as dbt_change_type, source_data.* from insertions_source_data as source_data left outer join snapshotted_data on snapshotted_data.dbt_unique_key = source_data.dbt_unique_key where snapshotted_data.dbt_unique_key is null or ( snapshotted_data.dbt_unique_key is not null and ( (snapshotted_data.dbt_valid_from < source_data.updated_at) ) ) ), updates as ( select 'update' as dbt_change_type, source_data.*, snapshotted_data.dbt_scd_id from updates_source_data as source_data join snapshotted_data on snapshotted_data.dbt_unique_key = source_data.dbt_unique_key where ( (snapshotted_data.dbt_valid_from < source_data.updated_at) ) ), deletes as ( select 'delete' as dbt_change_type, source_data.*, current_timestamp() as dbt_valid_from, current_timestamp() as dbt_updated_at, current_timestamp() as dbt_valid_to, snapshotted_data.dbt_scd_id from snapshotted_data left join deletes_source_data as source_data on snapshotted_data.dbt_unique_key = source_data.dbt_unique_key where source_data.dbt_unique_key is null ) select * from insertions union all select * from updates union all select * from deletes ); ``` mergeå®è¡ã¯ãšãªå
šæã ïŒã¯ãªãã¯ã§å±éïŒ ```sql merge into `sample-project`.`sample_dataset`.`sample_table` as DBT_INTERNAL_DEST using `sample-project`.`sample_dataset`.`sample_table__dbt_tmp` as DBT_INTERNAL_SOURCE on DBT_INTERNAL_SOURCE.dbt_scd_id = DBT_INTERNAL_DEST.dbt_scd_id when matched and DBT_INTERNAL_DEST.dbt_valid_to is null and DBT_INTERNAL_SOURCE.dbt_change_type in ('update', 'delete') then update set dbt_valid_to = DBT_INTERNAL_SOURCE.dbt_valid_to when not matched and DBT_INTERNAL_SOURCE.dbt_change_type = 'insert' then insert (`id`, `foo`, `bar`, `created_at`, `updated_at`, `dbt_updated_at`, `dbt_valid_from`, `dbt_valid_to`, `dbt_scd_id`) values (`id`, `foo`, `bar`, `created_at`, `updated_at`, `dbt_updated_at`, `dbt_valid_from`, `dbt_valid_to`, `dbt_scd_id`) ``` äžèšã¯ãšãªå
ã®åCTEã§è¡ãããåŠçããã£ãããŸãšãããšä»¥äžã®ãããªåŠçã®ãããŒã«ãªããŸãã åŠçã®è©³çްã詳ããèŠãŠããããã®ã§ãããã¯ãšãªèªäœãã¡ãã£ãšé·ãã®ã§ãinsert, update, deleteããããã®åŠçã«åå²ããŠè©³çްãèŠãŠããããšæããŸãïŒ snapshotå
éšåŠçã®è©³çް deleteåŠçïŒå®å
ããŒãã«ã«ååšããã¬ã³ãŒãããœãŒã¹ããŒãã«ã§deleteãããŠããå Žå tmpããŒãã«çæã¯ãšãªã®ãã¡ããœãŒã¹åŽã§deleteãããã¬ã³ãŒããmergeçšã¬ã³ãŒãã«å€æããåŠçã®æç² ïŒã¯ãªãã¯ã§å±éïŒ -- å®å
å±¥æŽããŒãã«ããå±¥æŽã確å®ããŠããªãã¬ã³ãŒããæœåº snapshotted_data as ( select *, -- unique_keyã«æå®ããã«ã©ã ãdbt_unique_keyãšãã id as dbt_unique_key from {{ å®å
ããŒãã« }} where dbt_valid_to is null ), deletes_source_data as ( select *, -- unique_keyã«æå®ããã«ã©ã ãdbt_unique_keyãšãã id as dbt_unique_key from {{ ãœãŒã¹ããŒãã« }} ) deletes as ( select ' delete ' as dbt_change_type, source_data.*, ãããããããããããããããã current_timestamp ()ã as dbt_valid_from, ãããããããããããããããã current_timestamp ()ã as dbt_updated_at, ãããããããããããããããã current_timestamp ()ã as dbt_valid_to, snapshotted_data.dbt_scd_id from snapshotted_data left join deletes_source_data as source_data on snapshotted_data.dbt_unique_key = source_data.dbt_unique_key where source_data.dbt_unique_key is null ) tmpããŒãã«çæã®åŠçã®å
èš³ã¯ä»¥äžã®ããã«ãªããŸãã ãåŠçã®æŠèŠã - å±¥æŽã確å®ããŠããªã(valid_toã«å€ãå
¥ã£ãŠããªã)ã¬ã³ãŒã矀ãå®å
ããŒãã«ããæœåº - å±¥æŽã確å®ããŠããªãã¬ã³ãŒãã®ãã¡ããœãŒã¹ããŒãã«ã«ååšããªã(åé€ããã)ã¬ã³ãŒãã«çµã蟌㿠- dbt_valid_from, dbt_valid_toãã¯ãšãªã®å®è¡æå»ã«èšå® - dbt_change_typeãâdeleteâã«èšå® ãœãŒã¹ããŒãã«åŽã§åé€ãããmergeçšã¬ã³ãŒããmergeããã¯ãšãª ïŒã¯ãªãã¯ã§å±éïŒ merge into {{å®å
ããŒãã«}} using {{ããŒãžçštmpããŒãã«}} on {{å®å
ããŒãã«}}.dbt_scd_id = {{ããŒãžçštmpããŒãã«}}.dbt_scd_id when matched and {{å®å
ããŒãã«}}.dbt_valid_to is null and {{ããŒãžçštmpããŒãã«}}.dbt_change_type in ( ' delete ' ) then update set dbt_valid_to = DBT_INTERNAL_SOURCE.dbt_valid_to ãåŠçã®æŠèŠã - dbt_scd_idãããŒã«ããŠå®å
ããŒãã«ãšããŒãžçštmpããŒãã«ãçµå - å®å
ããŒãã«ã®å±¥æŽãæªç¢ºå®ã§ãtmpããŒãã«ã®dbt_change_typeãâdeleteâã®å Žå - å®å
ããŒãã«ã®dbt_valid_toãtmpããŒãã«ã®dbt_valid_to(ã¯ãšãªå®è¡æå»)ã«äžæžã 以äžå³ã«è¡šãããããªåŠçã®æµãã«ãã£ãŠããœãŒã¹ããŒãã«åŽã§åé€ãããã¬ã³ãŒãdbt_valid_toã«snapshotæã®æå»ãå
¥ãããã«ãªããŸãã updateåŠçïŒå®å
ããŒãã«ãšæ¯èŒããŠãœãŒã¹ããŒãã«ã®ã¬ã³ãŒããupdateãããŠããå Žå tmpããŒãã«çæã¯ãšãªã®ãã¡ããœãŒã¹åŽã§updateãããã¬ã³ãŒããmergeçšã¬ã³ãŒãã«å€æããåŠçã®æç² ïŒã¯ãªãã¯ã§å±éïŒ -- å®å
å±¥æŽããŒãã«ããå±¥æŽã確å®ããŠããªãã¬ã³ãŒããæœåº snapshotted_data as ( select *, -- unique_keyã«æå®ããã«ã©ã ãdbt_unique_keyãšãã id as dbt_unique_key from {{ å®å
ããŒãã« }} where dbt_valid_to is null ), updates_source_data as ( select *, -- unique_keyã«æå®ããã«ã©ã ãdbt_unique_keyãšãã id as dbt_unique_key, updated_at as dbt_updated_at, updated_at as dbt_valid_from, updated_at as dbt_valid_to from {{ ãœãŒã¹ããŒãã« }} ), updates as ( select ' update ' as dbt_change_type, source_data.*, snapshotted_data.dbt_scd_id from updates_source_data as source_data join snapshotted_data on snapshotted_data.dbt_unique_key = source_data.dbt_unique_key where ( (snapshotted_data.dbt_valid_from < source_data.updated_at) ) ) ãåŠçã®æŠèŠã - å±¥æŽã確å®ããŠããªãã¬ã³ãŒã矀ãå®å
ããŒãã«ããæœåº - ãœãŒã¹ããŒãã«ããæœåºããã¬ã³ãŒãã®dbt_valid_from, dbt_valid_toãçŸåšæå»ã«èšå® - å±¥æŽã確å®ããŠããªãã¬ã³ãŒãã®ãã¡ãå®å
ã®dbt_valid_fromããåŸã«updated_atããœãŒã¹ããŒãã«ã«ååšããã¬ã³ãŒãã«çµã - dbt_change_typeãâupdateâã«èšå® ãœãŒã¹ããŒãã«åŽã§updateãããmergeçšã¬ã³ãŒããmergeããã¯ãšãª ïŒã¯ãªãã¯ã§å±éïŒ merge into {{å®å
ããŒãã«}} using {{ããŒãžçštmpããŒãã«}} on {{å®å
ããŒãã«}}.dbt_scd_id = {{ããŒãžçštmpããŒãã«}}.dbt_scd_id when matched and {{å®å
ããŒãã«}}.dbt_valid_to is null and {{ããŒãžçštmpããŒãã«}}.dbt_change_type in ( ' update ' ) then update set dbt_valid_to = DBT_INTERNAL_SOURCE.dbt_valid_to ãåŠçã®æŠèŠã - dbt_scd_idãããŒã«ããŠå®å
ããŒãã«ãšããŒãžçštmpããŒãã«ãçµå - å®å
ããŒãã«ã®å±¥æŽãæªç¢ºå®ã§ãtmpããŒãã«ã®dbt_change_typeãâupdateâã®å Žå - å®å
ããŒãã«ã®dbt_valid_toãtmpããŒãã«ã®dbt_valid_to(çŸåšæå»)ã«äžæžã 以äžå³ã«è¡šãããããªåŠçã®æµãã«ãã£ãŠãå®å
ããŒãã«ã®å±¥æŽãæªç¢ºå®ã®ããŒã¿ã®ãã¡ããœãŒã¹ã§æŽæ°ãèµ°ã£ãã¬ã³ãŒãã®dbt_valid_toã«ã¹ãããã·ã§ããæã®æ¥æãå
¥ããŸãã insertåŠçïŒå®å
ããŒãã«ã«ç¡ãã¬ã³ãŒãããœãŒã¹ããŒãã«åŽã«æ°èŠã§äœæãããŠããå Žå tmpããŒãã«çæã¯ãšãªã®ãã¡ãinsert察象ã®ã¬ã³ãŒããmergeçšã¬ã³ãŒãã«å€æããåŠçã®æç² ïŒã¯ãªãã¯ã§å±éïŒ -- å®å
å±¥æŽããŒãã«ããå±¥æŽã確å®ããŠããªãã¬ã³ãŒããæœåº snapshotted_data as ( select *, -- unique_keyã«æå®ããã«ã©ã ãdbt_unique_keyãšãã id as dbt_unique_key from {{ å®å
ããŒãã« }} where dbt_valid_to is null ), insertions_source_data as ( select *, id as dbt_unique_key, updated_at as dbt_updated_at, updated_at as dbt_valid_from, nullif (updated_at, updated_at) as dbt_valid_to, to_hex(md5( concat ( coalesce ( cast (id as string), '' ), ' | ' , coalesce ( cast (updated_at as string), '' )))) as dbt_scd_id from {{ ãœãŒã¹ããŒãã« }} ), insertions as ( select ' insert ' as dbt_change_type, source_data.* from insertions_source_data as source_data left outer join snapshotted_data on snapshotted_data.dbt_unique_key = source_data.dbt_unique_key where snapshotted_data.dbt_unique_key is null or ( snapshotted_data.dbt_unique_key is not null and ( (snapshotted_data.dbt_valid_from < source_data.updated_at) ) ) ), ãåŠçã®æŠèŠã - ãœãŒã¹ããŒãã«ã®unique_keyã«ããŠããã«ã©ã ãšupdated_atã«æå®ããŠããã«ã©ã ãçµã¿åãããŠsurrogate_keyãçæ - ãœãŒã¹ããŒãã«ã«å¯ŸããŠå±¥æŽæªç¢ºå®ã®å®å
ããŒãã«ãLEFT JOINããŠä»¥äžã®æ¡ä»¶ã«çµã - å®å
ããŒãã«ã«æå®ããunique_keyãååšããªããããœãŒã¹ããŒãã«ã«ã¯ååšããã¬ã³ãŒã - å®å
ããŒãã«ã«æå®ããunique_keyã®ã¬ã³ãŒããååšããŠããœãŒã¹ããŒãã«åŽã®updated_atãå®å
ããŒãã«ã®valid_fromãããåŸã®ã¬ã³ãŒã - dbt_change_typeãâinsertâã«èšå® ãœãŒã¹ããŒãã«åŽã§insertãããmergeçšã¬ã³ãŒããmergeããã¯ãšãª ïŒã¯ãªãã¯ã§å±éïŒ merge into {{å®å
ããŒãã«}} using {{ããŒãžçštmpããŒãã«}} on {{å®å
ããŒãã«}}.dbt_scd_id = {{ããŒãžçštmpããŒãã«}}.dbt_scd_id when not matched and {{ããŒãžçštmpããŒãã«}}.dbt_change_type = ' insert ' then insert (`id`, `foo`, `bar`, `created_at`, `updated_at`, `dbt_updated_at`, `dbt_valid_from`, `dbt_valid_to`, `dbt_scd_id`) values (`id`, `foo`, `bar`, `created_at`, `updated_at`, `dbt_updated_at`, `dbt_valid_from`, `dbt_valid_to`, `dbt_scd_id`) ãåŠçã®æŠèŠã - dbt_scd_idãããŒã«ããŠå®å
ããŒãã«ãšããŒãžçštmpããŒãã«ãçµå - dbt_scd_idããããããªããŠãdbt_change_type=âupdateâã®å Žåã«insertåŠçãå®è¡ - å®å
ããŒãã«ã®dbt_valid_toãtmpããŒãã«ã®dbt_valid_to(çŸåšæå»)ã«äžæžã 以äžå³ã«è¡šãããããªåŠçã®æµãã«ãã£ãŠãæå®ãããŠããŒã¯ããŒãå®å
ã«ååšããªãããå±¥æŽãæªç¢ºå®ã®ã¬ã³ãŒãã®ãã¡ãœãŒã¹åŽã§ååå®è¡ããupdateãèµ°ã£ããã®ãinsertãããŸãã checkæŠç¥ã®å Žå äžã§ç޹ä»ããã®ã¯ snapshot_strategy=timestamp ã®å Žåã®ã¹ãããã·ã§ããã®æåã§ããããœãŒã¹ããŒãã«åŽã§ updated_at ã«æå®ããã«ã©ã ãæŽæ°ãããå Žåã«ããã¹ãŠã®ããããã£ã®æ
å ±ãå±¥æŽçã«ä¿æãããã®ã§ãã dbtã«ã¯ããäžã€ã®ã¹ãããã·ã§ããæŠç¥ãšããŠã check æŠç¥ããããŸãã {% snapshot snapshotted_sample_table %} {{ config( target_schema= ' sample_dataset ' , strategy= ' check ' , unique_key= ' id ' , invalidate_hard_deletes= True , check_cols=[ ' foo ' , ' bar ' , ' created_at ' , ' updated_at ' , ], ) }} select * from {{ source( ' sample_dataset ' , ' sample_data ' ) }} {% endsnapshot %} ãã®ã¢ãã«ã§ã¯å
šã«ã©ã ãéžæããŠããŸãããç¹å®ã®ã«ã©ã ã®å€æŽã®ã¿ãå±¥æŽçã«ãã©ããã³ã°ããä»çµã¿ã§ãã strategy=check ã«ãããŠãã strategy=timestamp ã®æãšåæ§ã«ãsnapshotåŠçã¯tmpããŒãã«ãäœæããã¯ãšãªãšmergeåŠçãå®è¡ããã¯ãšãªã«åå²ãããŸãã strategy=checkã®å Žåã®tmpããŒãã«äœæã¯ãšãª ïŒã¯ãªãã¯ã§å±éïŒ strategy=checkã®å Žåã®mergeå®è¡ã¯ãšãª ïŒã¯ãªãã¯ã§å±éïŒ mergeå®è¡ã¯ãšãªã¯strategy=timestampã®æãšå€ããããtmpããŒãã«ã®çææ¹æ³ãç°ãªã£ãŠããã®ã§ã詳ããèŠãŠããããšæããŸã checkæŠç¥ã®è©³çް insert çšããŒã¿ã update çšããŒã¿ãåºåããCTEã§ã¯ã以äžã®ãããªWHEREæ¡ä»¶ã䜿çšãããŸãã (( snapshotted_data.`foo` != source_data.`foo` or ( ((snapshotted_data.`foo` is null ) and not (source_data.`foo` is null )) or (( not snapshotted_data.`foo` is null ) and (source_data.`foo` is null )) ) or snapshotted_data.`bar` != source_data.`bar` or ( ((snapshotted_data.`bar` is null ) and not (source_data.`bar` is null )) or (( not snapshotted_data.`bar` is null ) and (source_data.`bar` is null )) ) or snapshotted_data.`created_at` != source_data.`created_at` or ( ((snapshotted_data.`created_at` is null ) and not (source_data.`created_at` is null )) or (( not snapshotted_data.`created_at` is null ) and (source_data.`created_at` is null )) ) or snapshotted_data.`updated_at` != source_data.`updated_at` or ( ((snapshotted_data.`updated_at` is null ) and not (source_data.`updated_at` is null )) or (( not snapshotted_data.`updated_at` is null ) and (source_data.`updated_at` is null )) ) )) ãã®æ¡ä»¶ã«ãããinsert ãš update ã®å¯Ÿè±¡ãšãªãã¬ã³ãŒãã®æœåºæ¡ä»¶ã¯æ¬¡ã®ããã«ãªããŸãã insertçšããŒã¿ã®æœåºæ¡ä»¶ ( å®å
ã«ãŠããŒã¯ããŒãååšããªã ) OR ( (å®å
ã«ãŠããŒã¯ããŒãååšãã) AND (ãŠããŒã¯ããŒä»¥å€ã®check_colsã«æå®ããã«ã©ã ããå®å
ãšãœãŒã¹ã§äœãããå€åãçºçããŠãã) ) updateçšããŒã¿ã®æœåºæ¡ä»¶ (å®å
ã«ãŠããŒã¯ããŒãååšãã) AND (ãŠããŒã¯ããŒä»¥å€ã®check_colsã«æå®ããã«ã©ã ããå®å
ãšãœãŒã¹ã§äœãããå€åãçºçããŠãã) checkã§æå®ãããã«ã©ã ã®å€æŽãã©ã®ããã«è¿œè·¡ããŠãããã確èªã§ããŸããã ãŸãšã ä»åã¯dbt snapshotã®å
éšåŠçãdelete, update, insertã®åŠçã«åè§£ããŠèª¬æããŠã¿ãŸããã å
¬åŒããã¥ã¡ã³ãã§èª¬æãããŠããéãã®åŠçãçæãããSQLã«ãã£ãŠè¡ãããŠããããšã確èªã§ããŸããã dbt snapshotã䜿çšããŠããéã«ãæåŸ
ããæåãåŸãããªãå Žåãäœããããšã©ãŒãçºçãããšãã«ããã®æ
å ±ã圹ç«ãŠã°å¹žãã§ãïŒ Weâre Hired ã¿ã€ããŒã§ã¯ãäžç·ã«åãã¡ã³ããŒãåéããŠããŸãïŒïŒ product-recruit.timee.co.jp