Итак, у меня есть две таблицы, в которых я хочу сделать left join
и отфильтровать строки, где мой столбец date
из df1
находится между столбцами from
и to
из df2
.
Обратите внимание на row 6
, у которого нет ClockInDate
, что в конечном итоге вызовет проблему.
df1 :
Company Resource ClockInDate
0 A ResA 2019-02-09
1 A ResB 2019-02-09
2 A ResC 2019-02-09
3 B ResD 2019-02-09
4 B ResE 2019-02-09
5 B ResF 2019-02-09
6 B ResG NaT
df2 :
Company Resource EffectiveFrom EffectiveTo
0 A ResA 2018-01-01 2018-12-31
1 A ResA 2019-01-01 2099-12-31
2 A ResB 2018-01-01 2018-12-31
3 A ResB 2019-01-01 2099-12-31
4 B ResE 2018-01-01 2018-12-31
5 B ResE 2019-01-01 2099-12-31
6 B ResF 2018-01-01 2018-12-31
7 B ResF 2019-01-01 2099-12-31
8 B ResG 2018-01-01 2018-12-31
9 B ResG 2019-01-01 2099-12-31
Я думал, что смогу сделать это с left merge
в пандах и после этого применить фильтр.
Но это дает другой вывод.
Таким образом, в SQL вы можете включить этот фильтр в предложение ON
следующим образом, но это не то же самое, что включение после фильтра в предложении WHERE
:
SELECT t1.company,
t1.resource,
t2.company,
t2.resource,
t1.ClockInDate,
t2.EffectiveFrom,
t2.EffectiveTo
FROM table1 t1
LEFT JOIN table2 t2 ON t1.resource = t2.resource
AND t1.company = t2.company
AND t1.ClockInDate BETWEEN t2.EffectiveFrom AND t2.EffectiveTo
Notice часть: AND t1.ClockInDate BETWEEN t2.EffectiveFrom AND t2.EffectiveTo
Примечание: в коде SQL df1
равно t1
и df2
равно t2
Вывод SQL (Это мой ожидаемый вывод):
t1.Company t1.Resource t1.ClockInDate t2.EffectiveFrom t2.EffectiveTo
0 A ResA 2019-02-09 2019-01-01 2099-12-31
1 A ResB 2019-02-09 2019-01-01 2099-12-31
2 A ResC NaT NaT NaT
3 B ResD NaT NaT NaT
4 B ResE 2019-02-09 2019-01-01 2099-12-31
5 B ResF 2019-02-09 2019-01-01 2099-12-31
6 B ResG NaT NaT NaT
Так что я это мой код в Python
:
Выход Python
df_merge = pd.merge(df1, df2, on=['Company', 'Resource'], how='left')
df_final = df_merge[df_merge.ClockInDate.between(df_merge.EffectiveFrom, df_merge.EffectiveTo) | df_merge.EffectiveFrom.isnull()]
#Output:
Company Resource ClockInDate EffectiveFrom EffectiveTo
1 A ResA 2019-02-09 2019-01-01 2099-12-31
3 A ResB 2019-02-09 2019-01-01 2099-12-31
4 A ResC 2019-02-09 NaT NaT
5 B ResD 2019-02-09 NaT NaT
7 B ResE 2019-02-09 2019-01-01 2099-12-31
9 B ResF 2019-02-09 2019-01-01 2099-12-31
Обратите внимание, что последняя строка с ресурсом ResG
не включена в вывод Python.
Код для копирования и вставки для воспроизведения DataFrames
df1 = pd.DataFrame({'Company':['A', 'A', 'A', 'B', 'B', 'B', 'B'],
'Resource':['ResA', 'ResB','ResC', 'ResD', 'ResE', 'ResF', 'ResG'],
'ClockInDate':['2019-02-09', '2019-02-09', '2019-02-09', '2019-02-09', '2019-02-09', '2019-02-09', '']})
df1['ClockInDate'] = pd.to_datetime(df1.ClockInDate)
df2 = pd.DataFrame({'Company':['A','A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B'],
'Resource':['ResA', 'ResA', 'ResB', 'ResB', 'ResE', 'ResE', 'ResF', 'ResF', 'ResG', 'ResG'],
'EffectiveFrom':['2018-01-01', '2019-01-01', '2018-01-01', '2019-01-01', '2018-01-01', '2019-01-01', '2018-01-01', '2019-01-01', '2018-01-01', '2019-01-01'],
'EffectiveTo':['2018-12-31', '2099-12-31', '2018-12-31', '2099-12-31', '2018-12-31', '2099-12-31', '2018-12-31', '2099-12-31', '2018-12-31', '2099-12-31']})
df2['EffectiveFrom'] = pd.to_datetime(df2.EffectiveFrom)
df2['EffectiveTo'] = pd.to_datetime(df2.EffectiveTo)