【问题标题】:Dynamic conditional joins in BigQueryBigQuery 中的动态条件联接
【发布时间】:2020-07-27 18:41:20
【问题描述】:

我正在尝试在 BigQuery 中编写一个动态条件语句,以根据特定条件动态连接表。单个 ID 可以有 1 个或多个条件。 如何动态地“过滤”一系列 ID 条件(使用表 1、2 和 3)以将一组 masterProductIds 放入我的 Final 表中?

表 1 - Identification_table

表 2 - 归档表

表 3 - 价格

在这种情况下,我们需要为 Id 1 评估 3 个条件,为 Id 2 评估 2 个条件,为 Id 3 评估 1 个条件。

在我们也有价格条件的情况下,它应该加入价格表并根据表1中的运算符和值进行过滤。至于产品条件,我不必加入任何表,我只是按照表 1 中的值取值。

我期望的最终结果集。

决赛桌

到目前为止我做了什么:

select masterProductId, row_number() over (partition by id ) sq
from `filing_table` p 
left join `identification_table` pc
on case when subject = 'brand' then p.brandName when subject='category' then categoryName end = pc.boundaryValue
--on p.brandName = pc.boundaryValue or p.categoryName = boundaryValue
left join `price` pp
on p.code = pp.code
where 1=1
and pc.code = 'Id 2'
--and pp.RRP < safe_cast(pc1.boundaryValue as float64)

这将对所有内容进行整体评估。我不知道如何逐组评估 ID。

【问题讨论】:

  • 非常有趣的“挑战” - 您是否灵活地应对设置中的一些更改 - 1) 更改 Table2 中的列名,以便它们匹配 Table1 中列主题的值 2) 将 Table1 运算符列的值替换为相应的BigQuery 运算符 - 像 = 而不是 is equal&lt; 而不是 less than 等?
  • 我无法更改表 2 中的列名以匹配表 1 中的主题值 2.) 可以灵活地替换运算符的值,但最好在临时表或临时表中
  • 所以,在这种情况下,您可以更改主题列的值以匹配 table2 的列名 - 对吧?然后所有preferably in a temp or staging table 都可以处理,因为它不是您问题的重点——同意吗?您/我们需要在这里专注于主要挑战,其他一切留待以后调整/调整等。同时,请查看How to create a Minimal, Reproducible Example
  • 是的,你的假设是正确的,这听起来像是一个计划

标签: sql join google-bigquery coalesce


【解决方案1】:

以下是 BigQuery 标准 SQL 并假设表设置如下(经 cmets 中的 OP 同意)

identification_table

  SELECT 'Id 1' id, 'masterProductId' subject, '=' operator, '1007' value UNION ALL
  SELECT 'Id 1', 'brandName', '=', 'brand p' UNION ALL
  SELECT 'Id 1', 'categoryName', '=', 'category 1' UNION ALL
  SELECT 'Id 2', 'categoryName', '=', 'category 1' UNION ALL
  SELECT 'Id 2', 'price', '<', '130'  UNION ALL
  SELECT 'Id 3', 'categoryName', '=', 'category 3' 

filing_table

  SELECT 11 code, 'category 1' categoryName, 'brand p' brandName, 1001 masterProductId UNION ALL
  SELECT 22, 'category 1', 'brand z', 1002 UNION ALL
  SELECT 33, 'category 2', 'brand c', 1003 UNION ALL
  SELECT 44, 'category 2', 'brand v', 1004 UNION ALL
  SELECT 55, 'category 3', 'brand e', 1005

price

  SELECT 11 code, 3 price UNION ALL
  SELECT 22, 100 UNION ALL
  SELECT 33, 8 UNION ALL
  SELECT 44, 9 UNION ALL
  SELECT 77, 28 

因此,下面从filing_table 中提取那些符合identification_table 的所有标准的masterProductId

EXECUTE IMMEDIATE '''
SELECT masterProductId
FROM (
  SELECT f.*, price
  FROM `filing_table` f
  LEFT JOIN `price` p
  USING(code)
)
WHERE ''' || (  
  SELECT STRING_AGG('(' || condition || ')', ' OR ')
  FROM (
    SELECT STRING_AGG(FORMAT('(%s %s %s)', subject, operator, value), ' AND ') condition
    FROM `identification_table`,
    UNNEST([IF(subject IN ('price', 'masterProductId'), value, '"' || value || '"')]) value
    GROUP BY id
  ));

如果应用到答案顶部的样本数据 - 输出是

Row masterProductId  
1   1001     
2   1002     
3   1005     

【讨论】:

  • 感谢 Mikhail 的回答,它满足我的条件,但我如何使用 create or replace table `dataset.finalTable` as 语句将此结果保存在表中,或者将其保存为视图,然后在视图上使用 select 语句?因为这个执行语句会产生 2 个结果。
  • 只需在 select 语句之前添加 create or replace table `dataset.finalTable`,就像使用静态查询一样。
猜你喜欢
  • 2023-03-31
  • 2012-02-16
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2011-10-01
  • 2018-04-09
  • 2015-11-08
  • 1970-01-01
相关资源
最近更新 更多