使用 sas 或 sql 根据每月日期变量将新记录添加到 table
Using sas or sql add new records to table based on monthly date variables
我需要根据几个字段的值将 records/rows 添加到现有的 table。这些行基本上是每个不同 ID 的月份范围——大多数 ID 会有多个月,但有些只有一个月。
我有一个 first_date 字段和一个 last_date 字段,需要填写行,但是中间月份在两个日期之间,并为标识该行的行创建 "time id"月。
当前:
我认为您需要的是一个额外的 table,一个维度或映射 table,它将为您提供有关这些 dates/months 的信息。认为您可以加入几次以获得完整列表。
这是我所做的:
CREATE TABLE #tblCurrent
(ID INT,
First_Date VARCHAR(9),
Last_Date VARCHAR(9),
TotalMonths INT,
VAR1 INT,
VAR2 INT)
INSERT INTO #tblCurrent
SELECT 123,'01jan2015','01mar2015',3,5,2
union
SELECT 124,'01jul2015','01aug2015',2,5,2
union
SELECT 125,'01jan2015','01jan2015',1,5,2
这只是为了创建一个 table 模仿你的...
CREATE TABLE #Month
([MonthName] VARCHAR(9),
MonthRank INT)
INSERT INTO #Month
SELECT '01jan2015', 1
union SELECT '01feb2015', 2
union SELECT '01mar2015', 3
union SELECT '01apr2015', 4
union SELECT '01may2015', 5
union SELECT '01jun2015', 6
union SELECT '01jul2015', 7
union SELECT '01aug2015', 8
union SELECT '01sep2015', 9
union SELECT '01oct2015', 10
union SELECT '01nov2015', 11
union SELECT '01dec2015', 12
这是为了创建一个带有月份信息的 table,例如 order/rank。
SELECT c.*, m3.MonthRank Time_ID
FROM #tblCurrent c
JOIN #Month m ON c.First_Date = m.[MonthName]
JOIN #Month m2 ON c.Last_Date = m2.[MonthName]
JOIN #Month m3 ON m3.MonthRank >= m.MonthRank and m3.MonthRank <=m2.MonthRank
ORDER BY ID, m3.MonthRank
第三步提取第一个月(join m)、最后一个月(join m2)以及其间所有月份(m3)的信息。
如果您打算继续使用日期的“01jan2015”样式,构建日期维度 table 以在列中存储一堆相关信息可能会很有用....月, 年份等..
如果您使用的是摘要,您可以使用 FREQ total_months;在大多数 procs 或 proc freq 中,它是 WEIGHT。
我真的需要扩展,我想这就足够了。
data expand;
set <data-name>;
do time_id = 1 to total_months;
output;
end;
run;
更简洁的回复:
下面的代码应该处理困难的部分。请参阅 http://www.ats.ucla.edu/stat/sas/faq/enumerate.htm 了解如何处理 time_id。
/*your dataset*/
data tempy;
input id fd $ ld $ total_months time_id;
datalines;
123 jan mar 3 .
124 jul aug 2 .
125 jan jan 1 .
;
run;
/*make a copy of it*/
data tempy2;
set tempy;
run;
/*select the total_months and id variables into lists*/
proc sql noprint;
select total_months into: months_list
separated by " "
from tempy;
quit;
%put &months_list.;
proc sql noprint;
select id into: ids_list
separated by " "
from tempy;
quit;
%put &ids_list.;
%macro inserter;
/*for every row in the original dataset, keep track of id and how many total_months it has*/
%do i = 1 %to %sysfunc(countw(&months_list.));
%let this_id = %scan(&ids_list., &i.);
%let this_many_months = %scan(&months_list., &i.);
/*insert the same observation into the original dataset (total_months - 1) times for each row*/
%do j = 1 %to (&this_many_months. - 1);
proc sql;
insert into tempy select distinct * from tempy2 (where = (id = &this_id.));
quit;
%end;
%end;
/*sort*/
proc sort data = tempy;
by id;
run;
%mend inserter;
%inserter;
请注意,为了节省时间,我只是将 first_date 和 last_date 变量输入为字符串。您可以使用带有日期变量的 month() 函数来获取对处理 time_id 有用的信息(例如,month(01jul2015) = 7)。
我需要根据几个字段的值将 records/rows 添加到现有的 table。这些行基本上是每个不同 ID 的月份范围——大多数 ID 会有多个月,但有些只有一个月。
我有一个 first_date 字段和一个 last_date 字段,需要填写行,但是中间月份在两个日期之间,并为标识该行的行创建 "time id"月。
当前:
我认为您需要的是一个额外的 table,一个维度或映射 table,它将为您提供有关这些 dates/months 的信息。认为您可以加入几次以获得完整列表。
这是我所做的:
CREATE TABLE #tblCurrent
(ID INT,
First_Date VARCHAR(9),
Last_Date VARCHAR(9),
TotalMonths INT,
VAR1 INT,
VAR2 INT)
INSERT INTO #tblCurrent
SELECT 123,'01jan2015','01mar2015',3,5,2
union
SELECT 124,'01jul2015','01aug2015',2,5,2
union
SELECT 125,'01jan2015','01jan2015',1,5,2
这只是为了创建一个 table 模仿你的...
CREATE TABLE #Month
([MonthName] VARCHAR(9),
MonthRank INT)
INSERT INTO #Month
SELECT '01jan2015', 1
union SELECT '01feb2015', 2
union SELECT '01mar2015', 3
union SELECT '01apr2015', 4
union SELECT '01may2015', 5
union SELECT '01jun2015', 6
union SELECT '01jul2015', 7
union SELECT '01aug2015', 8
union SELECT '01sep2015', 9
union SELECT '01oct2015', 10
union SELECT '01nov2015', 11
union SELECT '01dec2015', 12
这是为了创建一个带有月份信息的 table,例如 order/rank。
SELECT c.*, m3.MonthRank Time_ID
FROM #tblCurrent c
JOIN #Month m ON c.First_Date = m.[MonthName]
JOIN #Month m2 ON c.Last_Date = m2.[MonthName]
JOIN #Month m3 ON m3.MonthRank >= m.MonthRank and m3.MonthRank <=m2.MonthRank
ORDER BY ID, m3.MonthRank
第三步提取第一个月(join m)、最后一个月(join m2)以及其间所有月份(m3)的信息。
如果您打算继续使用日期的“01jan2015”样式,构建日期维度 table 以在列中存储一堆相关信息可能会很有用....月, 年份等..
如果您使用的是摘要,您可以使用 FREQ total_months;在大多数 procs 或 proc freq 中,它是 WEIGHT。
我真的需要扩展,我想这就足够了。
data expand;
set <data-name>;
do time_id = 1 to total_months;
output;
end;
run;
更简洁的回复:
下面的代码应该处理困难的部分。请参阅 http://www.ats.ucla.edu/stat/sas/faq/enumerate.htm 了解如何处理 time_id。
/*your dataset*/
data tempy;
input id fd $ ld $ total_months time_id;
datalines;
123 jan mar 3 .
124 jul aug 2 .
125 jan jan 1 .
;
run;
/*make a copy of it*/
data tempy2;
set tempy;
run;
/*select the total_months and id variables into lists*/
proc sql noprint;
select total_months into: months_list
separated by " "
from tempy;
quit;
%put &months_list.;
proc sql noprint;
select id into: ids_list
separated by " "
from tempy;
quit;
%put &ids_list.;
%macro inserter;
/*for every row in the original dataset, keep track of id and how many total_months it has*/
%do i = 1 %to %sysfunc(countw(&months_list.));
%let this_id = %scan(&ids_list., &i.);
%let this_many_months = %scan(&months_list., &i.);
/*insert the same observation into the original dataset (total_months - 1) times for each row*/
%do j = 1 %to (&this_many_months. - 1);
proc sql;
insert into tempy select distinct * from tempy2 (where = (id = &this_id.));
quit;
%end;
%end;
/*sort*/
proc sort data = tempy;
by id;
run;
%mend inserter;
%inserter;
请注意,为了节省时间,我只是将 first_date 和 last_date 变量输入为字符串。您可以使用带有日期变量的 month() 函数来获取对处理 time_id 有用的信息(例如,month(01jul2015) = 7)。