【问题标题】:Duplicate rows based on "from" and "to" dates基于“from”和“to”日期的重复行
【发布时间】:2018-09-12 11:48:34
【问题描述】:

我有一个类似的表(SAS SQL 中的代码,但我可以转换来自 SQLServer 引擎的回复,因为我有一些经验):

proc sql;
   create table work.temp1
       (date_from num informat=date7. format=date7.,
        date_to num informat=date7.   format=date7.,
        some_number num);

insert into work.temp1
    values('15MAY2018'd,'26JUL18'd, 10);
QUIT;

结果:

我想将它转换为(通过一些巧妙的连接,可能还有一些带有日期和月份的临时表):

proc sql;
   create table work.temp2
       (date_from num informat=date7. format=date7.,
        date_to num informat=date7.   format=date7.,
        some_number num);

insert into work.temp2
    values('15MAY2018'd,'31MAY18'd, 10)
    values('1JUN2018'd,'30JUN18'd, 10)
    values('1JUL2018'd,'26JUL18'd, 10);
QUIT;

结果:

所有其他列都应重复。从和到的日期始终在一个日历日期中,但每一行可以在不同的年份(2016-2020)。

[编辑]:

Tom 解决方案看起来不错,但在我使用之前,我正在尝试开发 SQL 解决方案。

我在我的数据库中添加了一个“日历”表,它看起来像: 名称:work.calendar

现在我正在考虑的加入是这样的:

SELECT t1.* 
FROM work.temp1 t1 INNER JOIN 
     work.calendar t2 ON t1.date_from >= t2.month_FROM AND t1.date_to <= month_TO

但它显然不起作用。

【问题讨论】:

  • 为此的基本技术是建立一个人工日期列表,代表本月的第一天,并将您的实际数据加入其中,人工日期在实际数据日期之间,这样您的人工 JUN 和 JUL 与您的实际数据交叉。人工日期可以通过多种方式形成,通常涉及递增计数器和 DATEADD 样式操作,例如,如果您需要 1000 个日期,请选择至少有 1000 行的表并从中选择一个行号..跨度>
  • 或者,如果您有一个数字/日期表(许多 DBA 为这样的事情创建一个),那么只需以一种导致数据行重复的方式加入该表(artificialdates JOIN actualdates ON artificildates.date BETWEEN actual.from and actual.to 然后选择日期以 case 表示 (when actualenddate &lt; artificialdate+1month, actualdate, else artificialdate+1month )
  • 用 SQL 做起来并不容易,但用普通的 SAS 代码做起来并不难。

标签: sql sql-server sas proc-sql


【解决方案1】:

基本上,您希望将您的经期转换为月度记录。使用 SAS 代码很容易做到,但使用 SQL 会困难得多,因为它是基于集合而不是顺序处理。

让我们从创建测试数据开始吧。

data temp1;
  date_from='15MAY2018'd;
  date_to='26JUL18'd;
  some_number= 10;
  format date_: date9. ;
run;

intck() 函数可用于确定间隔数。 intnx() 函数可用于查找月份的开始/结束。您还可以添加代码行来重命名新变量并删除旧变量和循环计数器。

data want ;
  set temp1 ;
  do i=0 to intck('month',date_from,date_to);
    from = max(intnx('month',date_from,i,'b'),date_from);
    to = min(intnx('month',date_from,i,'e'),date_to);
    output;
  end;
  format from to date9.;
  rename from=date_from to=date_to;
  drop date_from date_to i ;
run;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-23
    • 2015-10-13
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 2021-10-08
    相关资源
    最近更新 更多