Hash join equivalent on PROC SQL between
Hash join equivalent on PROC SQL between
我通常使用 PROC SQL
因为当我加入 table 时也有日期条件(即 target_date
介于 start_date
和 end_date
).
在考虑 INNER JOIN
:
时,我已经能够成功地将其转换为散列连接
data hash_join;
if _n_ = 1 then do;
declare hash add1(dataset:'table_2',multidata: 'Y');
add1.defineKey('key_1');
add1.defineData('start_date','end_date','value_1');
add1.defineDone();
end;
format
start_date date9.
end_date date9.
value_1 10.5
;
set table_1 (keep=key_1 target_date);
if add1.find() = 0 then do until (add1.find_next());
if start_date le target_date le end_date then output;
end;
run;
与以下内容相同:
proc sql;
create table sql_join as select
b.start_date,
b.end_date,
b.value_1,
a.key_1,
a.target_date
from table_1 a
inner join table_2 b
on a.key_1 = b.key_1 and
a.target_date between b.start_date and b.end_date
;quit;
不过,我无法弄清楚 LEFT JOIN
的等价物是什么。 例如,如果没有JOIN
,我想输出,我认为这很简单:
if add1.find() ne 0 then output;
如果 JOIN
s 和日期介于两者之间,那似乎也很简单:
if add1.find() = 0 then do until (add1.find_next());
if start_date le target_date le end_date then output;
end;
但是如何从 table_1 中获取可能加入但在 start_date
和 end_date
之间没有 target_date
的其余记录? 例如, 假设 table_2
是一次 start_date
和 end_date
的销售,并且该销售直到 2 月 1 日才开始 key_1 = 'Clothes'
。如果我的table_1
有'Clothes'和1月1日的销售额,它会在键上JOIN
,但我想输出空白值。关于如何做到这一点有什么想法吗?
如有任何帮助,我们将不胜感激!
我认为您只需要跟踪是否有密钥,但不在范围内:
if add1.find() ^=0 then output;
else do;
found = 0;
do until (add1.find_next());
if start_date le target_date le end_date then do;
output;
found=1;
end;
end;
if ^found then output;
end;
没有可用于测试的数据,所以这只是我在 SO 中编写的代码。如果它不起作用,请告诉我。
您只需要跟踪是否找到了匹配项。由于您没有使用散列查找来跟踪事物的 'between' 部分,因此您不能使用它,所以您只能自己做。
看这个例子。我在这里修改 SASHELP.CLASS 使其看起来像您的输入表,然后添加一些逻辑以查看是否找到任何内容。
data table_1;
set sashelp.class;
rename age=target_date name=key_1;
drop height weight;
run;
data table_2;
set sashelp.class;
do _i = 1 to mod(_n_,3);
start_date = age-3+_i;
end_date = age+1-_i;
if start_date le end_date then output;
end;
rename name=key_1 height=value_1;
keep height weight start_date age end_date name;
run;
data hash_join;
if _n_ = 1 then do;
declare hash add1(dataset:'table_2',multidata: 'Y');
add1.defineKey('key_1');
add1.defineData('start_date','end_date','value_1');
add1.defineDone();
end;
format
start_date date9.
end_date date9.
value_1 10.5
;
set table_1 (keep=key_1 target_date);
if add1.find() = 0 then do until (add1.find_next());
if start_date le target_date le end_date then do;
found=1;
output;
end;
end;
call missing(of value_1); *full list of values to clear - all of hash data elements;
if not (found) then output;
run;
我通常使用 PROC SQL
因为当我加入 table 时也有日期条件(即 target_date
介于 start_date
和 end_date
).
在考虑 INNER JOIN
:
data hash_join;
if _n_ = 1 then do;
declare hash add1(dataset:'table_2',multidata: 'Y');
add1.defineKey('key_1');
add1.defineData('start_date','end_date','value_1');
add1.defineDone();
end;
format
start_date date9.
end_date date9.
value_1 10.5
;
set table_1 (keep=key_1 target_date);
if add1.find() = 0 then do until (add1.find_next());
if start_date le target_date le end_date then output;
end;
run;
与以下内容相同:
proc sql;
create table sql_join as select
b.start_date,
b.end_date,
b.value_1,
a.key_1,
a.target_date
from table_1 a
inner join table_2 b
on a.key_1 = b.key_1 and
a.target_date between b.start_date and b.end_date
;quit;
不过,我无法弄清楚 LEFT JOIN
的等价物是什么。 例如,如果没有JOIN
,我想输出,我认为这很简单:
if add1.find() ne 0 then output;
如果 JOIN
s 和日期介于两者之间,那似乎也很简单:
if add1.find() = 0 then do until (add1.find_next());
if start_date le target_date le end_date then output;
end;
但是如何从 table_1 中获取可能加入但在 start_date
和 end_date
之间没有 target_date
的其余记录? 例如, 假设 table_2
是一次 start_date
和 end_date
的销售,并且该销售直到 2 月 1 日才开始 key_1 = 'Clothes'
。如果我的table_1
有'Clothes'和1月1日的销售额,它会在键上JOIN
,但我想输出空白值。关于如何做到这一点有什么想法吗?
如有任何帮助,我们将不胜感激!
我认为您只需要跟踪是否有密钥,但不在范围内:
if add1.find() ^=0 then output;
else do;
found = 0;
do until (add1.find_next());
if start_date le target_date le end_date then do;
output;
found=1;
end;
end;
if ^found then output;
end;
没有可用于测试的数据,所以这只是我在 SO 中编写的代码。如果它不起作用,请告诉我。
您只需要跟踪是否找到了匹配项。由于您没有使用散列查找来跟踪事物的 'between' 部分,因此您不能使用它,所以您只能自己做。
看这个例子。我在这里修改 SASHELP.CLASS 使其看起来像您的输入表,然后添加一些逻辑以查看是否找到任何内容。
data table_1;
set sashelp.class;
rename age=target_date name=key_1;
drop height weight;
run;
data table_2;
set sashelp.class;
do _i = 1 to mod(_n_,3);
start_date = age-3+_i;
end_date = age+1-_i;
if start_date le end_date then output;
end;
rename name=key_1 height=value_1;
keep height weight start_date age end_date name;
run;
data hash_join;
if _n_ = 1 then do;
declare hash add1(dataset:'table_2',multidata: 'Y');
add1.defineKey('key_1');
add1.defineData('start_date','end_date','value_1');
add1.defineDone();
end;
format
start_date date9.
end_date date9.
value_1 10.5
;
set table_1 (keep=key_1 target_date);
if add1.find() = 0 then do until (add1.find_next());
if start_date le target_date le end_date then do;
found=1;
output;
end;
end;
call missing(of value_1); *full list of values to clear - all of hash data elements;
if not (found) then output;
run;