You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在BigQuery查询中为代理键选择指定字段

在BigQuery中基于指定字段生成哈希代理键

你当前用SHA256结合TO_JSON_STRING生成代理键时,会包含所有关联表的全部字段,想要仅基于SELECT语句中明确指定的输出字段生成哈希,可通过以下两种方式解决:

核心思路

原写法中STRUCT(user_, promo, ...)会将整个表对象的所有字段纳入哈希计算,只需改成仅包含SELECT中定义的、经过处理后的输出字段即可。

方式一:直接在STRUCT中列出目标字段

把SELECT里每一个要用来生成哈希的字段,明确写入STRUCT中,确保只包含这些最终输出的字段值。

方式二:通过子查询先筛选字段再生成哈希

先通过子查询提取所有需要的字段,再在外部查询中基于子查询结果生成哈希,避免重复编写字段列表,代码更简洁易维护。

修改后的代码示例

方式一:直接指定字段的写法

替换原查询中_surrogate_key部分的代码:

, SHA256(
    TO_JSON_STRING(
        STRUCT(
            _operating_country,
            id,
            `state`,
            city,
            zipcode,
            gender,
            date_of_birth,
            email,
            first_name,
            last_name,
            username,
            join_form_status,
            has_account,
            account_type,
            promocode,
            channel_acquisition,
            activation_timestamp,
            cancellation_timestamp,
            user_created_timestamp,
            card_expiry_timestamp
        )
    )
) AS _surrogate_key

方式二:子查询嵌套的写法

将原查询改写成子查询结构,外部查询负责生成哈希:

SELECT
    *,
    SHA256(TO_JSON_STRING(STRUCT(
        _operating_country,
        id,
        `state`,
        city,
        zipcode,
        gender,
        date_of_birth,
        email,
        first_name,
        last_name,
        username,
        join_form_status,
        has_account,
        account_type,
        promocode,
        channel_acquisition,
        activation_timestamp,
        cancellation_timestamp,
        user_created_timestamp,
        card_expiry_timestamp
    ))) AS _surrogate_key,
    CURRENT_DATE("UTC") AS _ingestion_date,
    CURRENT_DATETIME("UTC") AS _ingestion_datetime,
    valid_from,
    valid_to
FROM (
    SELECT
        user_._operating_country AS _operating_country
        /* DEMOGRAPHICS */
        , user_.userId AS id
        , UPPER(address_.county) AS `state`
        , UPPER(address_.city) AS city
        , UPPER(address_.postcode) as zipcode
        , CASE UPPER(user_.gender)
            WHEN "FEMALE" THEN "Female"
            WHEN "MALE" THEN "Male"
            ELSE "Unknown"
        END AS gender
        , user_.dob AS date_of_birth

        /* PII */
        , user_.email AS email
        , user_.firstName AS first_name
        , user_.lastName AS last_name
        , user_.username AS username
        
        /* ACCOUNT */
        , user_.joinFormStatus AS join_form_status
        , account.userId IS NOT NULL AS has_account
        , account.accountType AS account_type 
        , UPPER(
            COALESCE(
                parent_promo.code, parent_promo_ref.code, promo.code, promo_ref.code
            )
        ) AS promocode 
        , COALESCE(
            parent_promo_group.description, parent_promo_group_ref.description, promo_group_ref.description, promo_group_ref.description
        ) AS channel_acquisition
        /* TIMESTAMPS */
        , user_.activationDate AS activation_timestamp
        , user_.cancellationDate AS cancellation_timestamp
        , user_.created AS user_created_timestamp
        , account.cardExpiryDate AS card_expiry_timestamp
        , user_._scd_valid_from AS valid_from
        , user_._scd_valid_to AS valid_to

        FROM `user_` AS user_

        -- 保留原查询所有JOIN与WHERE逻辑
        LEFT JOIN `account` AS account 
            ON user_.userId = account.userId 
            AND user_._operating_country = account._operating_country
            AND user_._metadata_timestamp BETWEEN account._scd_valid_from AND COALESCE(account._scd_valid_to, CURRENT_TIMESTAMP())
    

        LEFT JOIN `promo` AS promo 
            ON UPPER(TRIM(user_.signupPromo)) = promo.code 
            AND user_._operating_country = promo._operating_country
            AND user_._metadata_timestamp BETWEEN promo._scd_valid_from AND COALESCE(promo._scd_valid_to, CURRENT_TIMESTAMP())
    

        LEFT JOIN `promo_group` AS promo_group 
            ON promo.groupId = promo_group.groupId 
            AND promo._operating_country = promo_group._operating_country
            AND promo._metadata_timestamp BETWEEN promo_group._scd_valid_from AND COALESCE(promo_group._scd_valid_to, CURRENT_TIMESTAMP())
    

        LEFT JOIN `promo_pair` AS promo_pair 
            ON IFNULL(promo.code, RIGHT(UPPER(TRIM(user_.signupPromo)), 2)) = promo_pair.pair 
            AND promo._operating_country = promo_pair._operating_country
        
        LEFT JOIN `promo_ref` AS promo_ref 
            ON promo_pair.inviteePromotion = promo_ref.code 
            AND promo_pair._operating_country = promo_ref._operating_country
        
        LEFT JOIN `promo_group_ref` AS promo_group_ref 
            ON promo_ref.groupId = promo_group_ref.groupId 
            AND promo_ref._operating_country = promo_group_ref._operating_country
            AND promo_ref._metadata_timestamp BETWEEN promo_group_ref._scd_valid_from AND COALESCE(promo_group_ref._scd_valid_to, CURRENT_TIMESTAMP())
      
          
          /* Parents of children users users */
        LEFT JOIN `relations` AS relations 
            ON user_.userId = relations.userId 
            AND relations.relationType = 'CHILD' 
            AND user_._operating_country = relations._operating_country
            AND user_._metadata_timestamp BETWEEN relations._scd_valid_from AND COALESCE(relations._scd_valid_to, CURRENT_TIMESTAMP())
        
        
        LEFT JOIN `parent` AS parent 
            ON relations.relatedId = parent.userId 
            AND relations._operating_country = parent._operating_country
            AND relations._metadata_timestamp BETWEEN parent._scd_valid_from AND COALESCE(parent._scd_valid_to, CURRENT_TIMESTAMP())
        
        
        LEFT JOIN `parent_promo` AS parent_promo 
            ON UPPER(TRIM(parent.signupPromo)) = parent_promo.code
            AND parent._operating_country = parent_promo._operating_country
            AND parent._metadata_timestamp BETWEEN parent_promo._scd_valid_from AND COALESCE(parent_promo._scd_valid_to, CURRENT_TIMESTAMP())
        
        
        LEFT JOIN `parent_promo_group` AS parent_promo_group 
            ON parent_promo.groupId = parent_promo_group.groupId 
            AND parent_promo._operating_country = parent_promo_group._operating_country
            AND parent_promo._metadata_timestamp BETWEEN parent_promo_group._scd_valid_from AND COALESCE(parent_promo_group._scd_valid_to, CURRENT_TIMESTAMP())
        
        
        LEFT JOIN `parent_promo_pair` AS parent_promo_pair 
            ON IFNULL(parent_promo.code, RIGHT(UPPER(TRIM(parent.signupPromo)), 2)) = parent_promo_pair.pair 
            AND IFNULL(parent_promo._operating_country, parent._operating_country) = parent_promo_pair._operating_country
                
        LEFT JOIN `parent_promo_ref` AS parent_promo_ref 
            ON parent_promo_pair.inviteePromotion = parent_promo_ref.code 
            AND parent_promo_pair._operating_country = parent_promo_ref._operating_country
        
        LEFT JOIN `parent_promo_group_ref` AS parent_promo_group_ref 
            ON parent_promo_ref.groupId = parent_promo_group_ref.groupId
            AND parent_promo_ref._operating_country = parent_promo_group_ref._operating_country
            AND parent_promo_ref._metadata_timestamp BETWEEN parent_promo_group_ref._scd_valid_from AND COALESCE(parent_promo_group_ref._scd_valid_to, CURRENT_TIMESTAMP())
        
        
        LEFT JOIN `address_` AS address_ 
            ON COALESCE(parent.userId, user_.userId) = address_.userId 
            AND COALESCE(parent._operating_country, user_._operating_country) = address_._operating_country
            AND COALESCE(parent._metadata_timestamp, user_._metadata_timestamp) BETWEEN address_._scd_valid_from AND COALESCE(address_._scd_valid_to, CURRENT_TIMESTAMP())
        
    
        WHERE GREATEST(
                    user_._ingestion_date
                    , address_._ingestion_date
                    , relations._ingestion_date
                    , account._ingestion_date
                    , promo._ingestion_date
                    , promo_group._ingestion_date
                    , promo_ref._ingestion_date
                    , promo_group_ref._ingestion_date
                    , parent._ingestion_date
                    , parent_promo._ingestion_date
                    , parent_promo_group._ingestion_date
                    , parent_promo_ref._ingestion_date
                    , parent_promo_group_ref._ingestion_date
                ) > (SELECT MAX(_ingestion_date) FROM `destination_table`)
) AS core_data

注意事项

  • 确保STRUCT中的字段与SELECT输出的字段完全匹配,包括别名和计算后的结果,保证哈希值准确对应最终输出内容。
  • 后续修改SELECT字段时,需同步更新STRUCT中的字段列表,避免哈希与实际字段不匹配。

内容的提问来源于stack exchange,提问作者mj8701

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 23:27:11