I have 2 tables with the following data:
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 |
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:
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.