簡體   English   中英

在 ID 上加入,如果 ID 不匹配,然后在其他列 BigQuery 上匹配

[英]JOIN on ID, IF ID doesn't match then match on other columns BigQuery

我有兩個要加入的表。 這些表有一個主鍵和外鍵,但在某些情況下鍵不匹配,我需要加入下一個最佳匹配。

我嘗試使用 case 語句並且它可以工作,但是因為連接並不完美。 它要么獲取不正確的值,要么復制記錄。

該表的工作方式是如果Info_ID不匹配,我們可以使用Lev1的組合,如果cust_start日期在Info_StartInfo_End之間

我需要一種方法來匹配 ID,然后 SQL 停止匹配該行。 但我不確定這是否是 BigQuery 可以做到的。

客戶表

Cust_ID Cust_InfoID Cust_name   Cust_Start  Cust_Lev1
1111    1           Amy         2021-01-01  A
1112    3           John        2020-01-01  D
1113    8           Bill        2020-01-01  D

信息表

Info_ID Info_Lev1   Info_Start  Info_End    state
1       A           2021-01-15  2021-01-14  NJ
3       D           2020-01-01  2020-12-31  NY
5       A           2021-01-01  2022-01-31  CA

預期結果

Cust_ID Cust_InfoID Info_ID Cust_Lev1   Cust_Start  Info_Start  Info_End    state
1111    1           1       A           2021-01-01  2021-01-15  2021-01-14  NJ
1112    3           3       D           2020-01-01  2020-01-01  2020-12-31  NY
1112    8           3       D           2020-01-01  2020-01-01  2020-12-31  NY

加入理念一:

CASE
  WHEN
    (Cust_InfoID = Info_ID) = true
    AND (Cust_Start BETWEEN Info_Start AND Info_End) = true
  THEN
    Cust_InfoID = Info_ID
  ELSE
    Cust_Start BETWEEN Info_Start AND Info_End
    and Info_Lev1 = Cust_Lev1
END

Output:
Cust_ID Cust_InfoID Info_ID Cust_Lev1   Cust_Start  Info_Start  Info_End    state
1111    1           5       A           2021-01-01  2021-01-01  2022-01-31  CA
1112    3           3       D           2020-01-01  2020-01-01  2020-12-31  NY
1113    8           3       D           2020-01-01  2020-01-01  2020-12-31  NY

這里的問題是 ID 匹配但日期不匹配,因此它使用 ELSE 語句加入。 這是不正確的

加入理念二:

CASE
  WHEN
    Cust_InfoID = Info_ID
  THEN
    Cust_InfoID = Info_ID
  ELSE
    Cust_Start BETWEEN Info_Start AND Info_End
    and Info_Lev1 = Cust_Lev1
END

Output:
Cust_ID Cust_InfoID Info_ID Cust_Lev1   Cust_Start  Info_Start  Info_End    state
1111    1           1       A           2021-01-01  2021-01-15  2021-01-14  NJ
1111    1           5       A           2021-01-01  2021-01-01  2022-01-31  CA
1112    3           3       D           2020-01-01  2020-01-01  2020-12-31  NY
1113    8           3       D           2020-01-01  2020-01-01  2020-12-31  NY

這里的問題是 ID 匹配但 ELSE 語句也匹配了錯誤的重復行。 這也是不正確的

此處的示例表:

with customer as (
    SELECT 1111 Cust_ID,1 Cust_InfoID,'Amy' Cust_name,'2021-01-01' Cust_Start,'A' Cust_Lev1
    UNION ALL 
    SELECT 1112,3,'John','2020-01-01','D'
    union all 
    SELECT 1113,8,'Bill','2020-01-01','D'
),
info as (
    select 1 Info_ID,'A' Info_Lev1,'2021-01-15' Info_Start,'2021-01-14' Info_End,'NJ' state
    union all 
    select 3,'D','2020-01-01','2020-12-31','NY'
    union all 
    select 5,'A','2021-01-01','2022-01-31','CA'
)
select Cust_ID,Cust_InfoID,Info_ID,Cust_Lev1,Cust_Start,Info_Start,Info_End,state
from customer 
join info on 
[case statement here]

該表的工作方式是,如果 Info_ID 不匹配,我們可以使用 Lev1 的組合,如果 cust_start 日期在 Info_Start 和 Info_End 之間

使用兩個left join ,每個條件一個:

select c.*,
       coalesce(ii.info_start, il.info_start),
       coalesce(ii.info_end, il.info_end),
       coalesce(ii.state, il.state)
from customer c left join
     info ii
     on c.cust_infoid = ii.info_id left join
     info il
     on ii.info_id is null and
        c.cust_lev1 = il.info_lev1 and
        c.cust_start between il.info_start and il.info_end

考慮下面(“用一個 JOIN 和一個 CASE 語句”按要求)

select any_value(c).*, 
  array_agg(i order by 
    case when c.cust_infoid = i.info_id then 1 else 2 end
    limit 1
  )[offset(0)].*
from `project.dataset.customer` c 
join `project.dataset.info` i
on c.cust_infoid = i.info_id 
or(
  c.cust_lev1 = i.info_lev1 and
  c.cust_start between i.info_start and i.info_end
)
group by format('%t', c)

當應用於您問題中的樣本數據時 - output 是

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM