【发布时间】:2019-02-19 11:42:00
【问题描述】:
我想按日期加入两个表(A 和 B)。由于日期不一定在表格中整齐排列,这一事实使情况变得复杂。也就是说,表 B 中的日期可能落在表 A 的条目之外或之间。
我怀疑在 SQL/SAS 中一定有一种简单的方法可以实现这一点,但我对这两种方法都很陌生,不知道怎么做。如果有人能指出我可以用来解决这个问题的具体解决方案、示例或功能,我将非常高兴。我在下面创建了一个虚构的案例来说明。
这是表 A 的外观示例(对于一位参与者):
Table A
-------------------------------------------+
participant start end
-------------------------------------------+
101 1-1-2010 26-4-2010
101 27-4-2010 2-10-2014
101 3-10-2014 4-1-2015
101 5-1-2015 31-8-2015
101 1-9-2015 12-10-2016
101 13-10-2016 31-12-2018
下面是需要连接到表 A 的表 B 的示例。如您所见,对于简单的左连接,日期差异太大:
Table B
---------------------------------------------------------+
participant start_date end_date Content
---------------------------------------------------------+
101 1-1-2012 31-8-2012 A
101 1-9-2012 31-8-2013 B
101 1-9-2013 31-8-2014 C
101 1-9-2014 2-10-2014 D
101 3-10-2014 31-8-2015 E
101 1-9-2015 31-1-2016 F
101 1-9-2015 31-1-2016 F
连接表 C 的想法是表 A 的每一行都由表 B 中的数据通知。我想从 B 中选择一个位于表 A 范围内的条目。如果 B 中的多个条目适合,则应该使用最近的一个。如果表 B 没有该时期的信息(如第一行的情况),则应使用最接近的信息。另一种说法是,我希望将 B 的最新信息添加到 A 的每一行。
Table C
----------------------------------------------------------------------+
participant startA endA startB endB Content
----------------------------------------------------------------------+
101 1-1-2010 26-4-2010 1-1-2012 31-8-2012 A
101 27-4-2010 2-10-2014 1-9-2013 31-8-2014 C
101 3-10-2014 4-1-2015 1-9-2014 2-10-2014 D
101 5-1-2015 31-8-2015 3-10-2014 31-8-2015 E
101 1-9-2015 12-10-2016 1-9-2015 31-1-2016 F
101 13-10-2016 31-12-2018 1-9-2015 31-1-2016 F
这是我第一次使用 SAS 和 SQL,所以我自己的努力效果很差。下面,我通过几个步骤将这两个表连接到一个过程中:我首先创建一个完整连接以获取表 A 和 B 的所有可能(相关)排列。然后我计算表 A 中数据之间的日期差异和 B. 最后,对于 A 的每个时期,我选择原始表中的数据之间的日期差异最小的行。
/* Create outer join of both tables*/
PROC SQL;
CREATE TABLE work.fulljoin AS
SELECT a.*, b.*
FROM work.table_A AS a
FULL JOIN work.table_B AS b ON a.participant = b.participant;
quit;
/* Group by ID and entry date of each period */
PROC SORT data=work.fulljoin;
BY participant startA;
RUN;
/* Calculate the date differences between tables A and B */
DATA work.fulljoin_wdelta;
SET work.fulljoin;
delta=abs(endA-endB);
RUN;
/* Remove unnecessary rows */
PROC SQL;
CREATE TABLE output.joined AS
SELECT * FROM work.fulljoin_wdelta
GROUP BY participant, startA
HAVING delta=min(delta);
QUIT;
但是,对于大型数据集(A 和 B 中的数百万行),这变得令人望而却步。此外,严格来说,此方法并不强制您将获取每个 A 周期的最新 B 数据,而只是获取结束日期最接近的 B 数据。
【问题讨论】:
-
您的表格 C 是您希望连接表格的外观示例,还是您迄今为止设法制作的最佳示例?如果是后者,请根据您的输入表 A 和 B 提供一个示例,说明您希望它的外观。
-
数百万行是 SAS 数据集还是远程数据库表?如果有,数据集上有哪些索引?
-
感谢您的 cmets! @user667489,表 C 是我想要摆脱的。理查德,这是关于 SAS 数据集的。