【问题标题】:How do I identify events that occurred in consecutive years?如何识别连续几年发生的事件?
【发布时间】:2019-06-18 17:41:23
【问题描述】:

我试图按月计算前三年连续发生的事件。例如:

Item     Type      Month      Year
Hat        S         May       2015
Shirt      P         June      2015
Hat        S         June      2015
Hat        S         May       2016
Shirt      P         May       2016
Hat        S         May       2017

我有兴趣查看同一个月内连续三年购买/出售了哪些商品。帽子分别于2015年、2016年、2017年5月售出;因此,我想确定这一点。衬衫是在 2015 年 6 月和 2016 年 5 月购买的。由于连续年份的月份不同,因此不符合条件。

基本上,我希望它能够回顾 3 年并识别每年同一个月内再次发生的购买/销售,最好使用指示变量。

我尝试了以下代码:

select distinct a.*
from dataset as a inner join dataset as b 
on a.type = b.type
and a.month = b.month
and a.item = b.item
and a.year = b.year-1 
and a.year = b.year-2;

我想得到:

Item     Type      Month      Year
Hat        S         May       2015
Hat        S         May       2016
Hat        S         May       2017

我想我应该补充一点,我的数据比 2015-2017 年更长。它跨越 10 年,但我想看看在这 10 年的跨度内是否有连续 3 年(或更多)。

【问题讨论】:

  • 有多种处理方法。尽管我们中的一些人可能对您的有趣问题很感兴趣,但我们讨厌做您的工作并进入您的学习过程。您做了什么尝试并需要具体帮助?
  • 我尝试了以下代码:select distinct a.* from dataset as a inner join dataset as b on a.type = b.type and a.month = b.month and a.item = b.item and a.year = b.year-1 and a.year = b.year-2;
  • 您必须使用 SQL 还是可以接受数据步骤?如果这些年是连续 5 年,你想要什么?前三个,后三个,全部 5 个?如果系列中有两个以上三年的序列,例如如果前三年是连续的并且最后三年是连续的,会发生什么?
  • 可以接受数据步骤。我希望至少连续三年。顺序无关紧要。只要我能识别其中一个,两个三年序列就可以了。

标签: sql if-statement sas conditional-statements


【解决方案1】:

有很多方法可以做到这一点,但是,SQL 中的一种方法是,将行限制为 ItemMonth2017。为了符合连续 3 年的资格,组内不同年份的计数应为 3。此类标准将处理重复数据,例如具有 3 个 S 型帽子和 3 个 P 型帽子的组。

select item, type, month, year
from have
where year between 2015 and 2017
group by item, month
having count(distinct year) = 3
order by item, type, month, year

对于识别组内运行的更一般的问题,SAS 数据步骤非常适合且功能强大。串行 DOW 循环技术首先根据某些条件在一系列行上循环,同时计算一个组指标——在这种情况下,连续年运行长度。第二个循环遍历相同的行并利用其中的组指标。

考虑这个例子,其中rungroup 是根据项目/月的年份相邻性计算的。一旦建立了运行组,就会应用双 DOW 技术。

data have;
  do comboid = 1 to 1000;
    itemid = ceil(10 * ranuni(123));
    typeid = ceil(2* ranuni(123));
    month = ceil(12 * ranuni(123));
    year = 2009 + floor (10 * ranuni(123));
    output;
  end;
run;

proc sort data=have;
  by itemid month year;
run;

data have_rungrouped;
  set have;
  by itemid month year;

  rungroup + (first.month or not first.month and year - lag(year) > 1);
run;

data want;
  do index = 1 by 1 until (last.rungroup);
    set have_rungrouped;
    by rungroup;

    * distinct number of years in rungroup;
    years_runlength = sum (years_runlength, first.rungroup or year ne lag(year));
  end;

  do index = 1 to index;
    set have_rungrouped;
    if years_runlength >= 3 then output;
  end;
run;

【讨论】:

  • 我想我应该补充一点,我的数据比 2015-2017 年更长。它跨越 10 年,但我想看看在这 10 年的跨度内是否有连续 3 年(或更多)。
【解决方案2】:

这是一个示例,它会检查是否有任何项目连续发生,并列出原始表中至少连续两年符合条件的所有项目:

DECLARE @table TABLE
(
    Item NVARCHAR(MAX),
    Type CHAR,
    Month NVARCHAR(MAX),
    Year INT
)

INSERT INTO @table VALUES
('Hat','S','May','2015'),
('Shirt','P','June','2015'),
('Hat','S','June','2015'),
('Hat','S','May','2016'),
('Shirt','P','May','2016'),
('Hat','S','May','2017')

SELECT * FROM @table
WHERE CONCAT(Item,Month) IN 
(
    SELECT CONCAT(group1.Item, group1.Month) FROM
    (
        SELECT Item,Year,Month FROM @table
        GROUP BY Year, Item, Month
    ) group1
    FULL OUTER JOIN 
    (
        SELECT Item,Year,Month FROM @table
        GROUP BY Year, Item, Month
    ) group2
    ON group1.Year = group2.Year + 1 AND group1.Item = group2.Item AND group1.Month = group2.Month
    WHERE group1.Item IS NOT NULL AND group2.Item IS NOT NULL
)
ORDER BY Item,Month,Year

如您所见,我在同一个月找到了与 year + 1 匹配的所有项目。

输出:

Hat S   May 2015
Hat S   May 2016
Hat S   May 2017

【讨论】:

    猜你喜欢
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多