简体   繁体   中英

left join using two columns and multiple conditions in bigquery

I have 2 tables with the following data:

Orders

code order_type order_date vendor_code
1 OD 2021-02-01 1
2 OD 2021-05-03 1
3 VD 2021-02-04 1
4 VD 2021-07-01 1

Contracts

contract_start_date contract_end_date contract_type commission_percentage vendor_code
2021-01-01 2021-02-28 OD 20 1
2021-01-01 2021-02-28 VD 25 1
2021-03-01 2021-04-30 OD 30 1
2021-06-01 2021-10-04 OD 35 1

I want to assign each order a commission percentage based on vendor_code, date and type. Here is the desired output:

Desired Output:

code order_type order_date vendor_code contract_type commission_percentage
1 OD 2021-02-01 1 OD 20
2 OD 2021-05-03 1 OD 30
3 VD 2021-02-04 1 VD 25
4 VD 2021-07-01 1 OD 35

First case is when the order_type is the same as contract type and the order date lies within contract_start_date and contract_end_date. This is the case for orders 1 and 3. However, in case this condition is not true, I want to get the latest contract with max contract_start_date before the order_date and I want to pick contract_type OD if it exists irrespective of order_type and if it doesn't then pick the latest VD contract (before the order_date). The only way that comes to mind is using a cross join after which I would need to have multiple case statements to reach this result. However, that would be very slow for my data as I have millions of records in orders and every vendor has a multitude of contracts.

Here is my current code that caters to orders 1 and 3 but I can't figure out orders 2 and 4.

with contracts as (select date('2021-01-01') as contract_start_date, date('2021-02-28') as contract_end_date, 'OD' as contract_type, 20 as commission_percentage
union all
select '2021-01-01', '2021-02-28', 'VD', 25
union all
select '2021-03-01', '2021-04-30', 'OD', 30
union all 
select '2021-06-01', current_date(), 'OD', 35
)
, orders as (
select 1 as code, 'OD' as order_type, date('2021-02-01') as order_date
union all 
select 2, 'OD', '2021-05-03'
union all
select 3, 'VD', '2021-02-04'
union all
select 4, 'VD', '2021-07-01')

select o.*, c.contract_type, c.commission_percentage
from orders o left join contracts c on o.order_type = c.contract_type and o.order_date between c.contract_start_date and c.contract_end_date

You might want to use the separate subqueries with cross join since left outer join without equal key field is not currently supported on BigQuery.

with
contracts as (
    select
        date('2021-01-01') as contract_start_date,
        date('2021-02-28') as contract_end_date,
        'OD' as contract_type,
        20 as commission_percentage
    union all select '2021-01-01', '2021-02-28', 'VD', 25
    union all select '2021-03-01', '2021-04-30', 'OD', 30
    union all select '2021-06-01', current_date(), 'OD', 35
),
orders as (
    select 1 as code, 'OD' as order_type, date('2021-02-01') as order_date
    union all select 2, 'OD', '2021-05-03'
    union all select 3, 'VD', '2021-02-04'
    union all select 4, 'VD', '2021-07-01'
),
latest_contracts_OD AS (
    select *
    from contracts
    WHERE contract_type = 'OD'
),
latest_contracts_VD AS (
    select *
    from contracts
    WHERE contract_type = 'VD'
)
select
    o.*,
    IFNULL(
        IFNULL(c.contract_type, lc_od.contract_type),
        lc_vd.contract_type
    ) as contract_type,
    IFNULL(
        IFNULL(c.commission_percentage, lc_od.commission_percentage),
        lc_vd.commission_percentage
    ) as commission_percentage,
from orders o
left join contracts c
    on o.order_type = c.contract_type
    and o.order_date between c.contract_start_date and c.contract_end_date
cross join latest_contracts_OD lc_od
left outer join latest_contracts_VD lc_vd
    on o.order_type = lc_vd.contract_type
    and o.order_date >= lc_vd.contract_start_date
WHERE o.order_date >= lc_od.contract_start_date
QUALIFY ROW_NUMBER() OVER (PARTITION BY code, order_type ORDER BY lc_od.contract_start_date DESC) = 1
order by code
;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM