sql - SAS:如何在多个级别上计算不同

标签 sql sas

SAS中是否有一种优雅的方法可以在不使用一系列sql语句的情况下在多个级别上计算“计数不同”?

假设我们正在计算唯一客户。 Joe已购买了2个大窗口部件和1个小窗口部件,这很简单,就可以将他算作1个大窗口部件的客户和1个小窗口部件的客户。但是我们还需要将他视为仅1个“小部件客户”,因此需要单独的SQL计算。事实证明,乔还购买了一个鼠标垫,因此当我们为“杂项产品”组计算唯一客户时,我们需要进行第三次SQL计算。乔从#1商店购买了所有这些东西,但是当我们计算“小商店编号区域”的杂项产品的唯一客户时,我们还必须考虑到Joe从#2商店购买的咖啡杯。另一个SQL计算。

SAS中有很多计算事物的方法,但是似乎没有简单的方法可以计算“不同”的事物。有什么建议么?

最佳答案

您在这里遇到了一些不同的问题,这取决于数据的结构。遗憾的是您没有提供,所以我决定!

我们将假设您有一个这样的数据集。您还可以在两行中购买两次LargeWidget(对于其他产品也是如此),对此没有任何影响。

data customers;
  length product $20;
  input name $ product $ store $ count;
datalines;
Joe SmallWidget Store1 1
Joe LargeWidget Store1 2
Joe Mousepad Store1 1
Joe TeaPitcher Store2 1
Jack SmallWidget Store2 1
Jack Mousepad Store1 1
Jane LargeWidget Store2 1
Jane Mousepad Store1 1
Jill LargeWidget Store3 1
;;;;
run;

然后,我们需要进行另一项设置:确定打算如何对事物进行分组。多标签格式允许您要求一个值落入多个存储桶(即,大型小部件和所有小部件)。这是一个例子,您可以在这里做很多不同的事情。您也可以从数据集中进行此操作(在proc格式中查找CNTLIN选项,或询问其他问题)。
proc format;
  value $prodgroup (multilabel default=20)
    SmallWidget = "Small Widgets"
    SmallWidget = Widgets
    LargeWidget = "Large Widgets"
    LargeWidget = Widgets
    Mousepad = Mousepads
    Mousepad = "Misc Products"
    TeaPitcher = "Tea Pitchers"
    TeaPitcher = "Misc Products"
  ;
  value $storeRegions (multilabel)
    Store1=Store1
    Store1=West
    Store2=Store2
    Store2=East
    Store3=Store3
    Store3=East
  ;
quit;

然后,我们面临一个大问题:SAS在计算“不同”的事物上很费力。这样做并不是真正做到的。我不知道为什么;制表确实应该,但事实并非如此。但是,将它们放在桶中确实做得很好,这确实是这里的难点。实际的唯一计数位可以在第二遍中完成(不管您的初始数据大小如何,这都会非常快,前提是您假设产品的种类少于数据点的种类)。
proc tabulate data=customers out=custdata;
  class product store /mlf preloadfmt order=data;  
  class name;
  format product $prodgroup20.;
  format store $storeRegions6.;
  tables (all store product store*product),name*n;
run;

proc tabulate data=custdata;
  class product store/missing;
  tables (product*store), n;
run;
MLF PRELOADFMT ORDER=DATA使multilabel位正常工作,并使其以有用的顺序出现(我认为)。您可以在NOTSORTED的value语句中添加PROC FORMAT以获得更多控制权,尽管第二个PROC TABULATE只会按顺序弄乱事情,因此我不会打扰。

在这种情况下,我们要做的是首先生成一个由客户创建的表,然后将该表输出到数据集;现在,只要在两个proc中都对分组进行了镜像(当然要减去NAME类!),就可以保证该数据集每个[无论分组]每位客户都包含一行。

此过程的一个不足之处是,它不会为那些具有0的产品生成行,而不必为您提供第二行列表,而是在SQL或数据步骤中执行。例如:
proc tabulate data=customers out=custdata2;
  class product store /mlf preloadfmt order=data;  
  class name;
  format product $prodgroup20.;
  format store $storeRegions6.;
  tables (all store product store*product),name*n/printmiss;
run;

proc sql;
  select product, store, sum(case when n>0 then 1 else 0 end) as count
  from custdata2
  group by product,store;
quit;

请注意对TABLE行的一项更改:printmiss,它指示Tabulate对任何可能的组合都使用一行。然后SQL完成其余工作。当然,如果您喜欢SQL,此SQL也可以更早地复制第二个Tabulate语句。

关于sql - SAS:如何在多个级别上计算不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27421565/

相关文章:

sas - proc 转置所需的最小变量数

sas - SAS 存储过程的 XML 语法

mysql - MySQL 中的 SQL 子查询

c# - 想要从下拉列表中的日期中删除时间?

mysql - 如何在一个语句中连接四个 MySQL 表

csv - 如何在 SAS 中导入多行 CSV

MySQL Where IN 数组

mysql - 在两个表中选择数据

powershell - 无法在同一个 PowerShell session 中运行同一个脚本两次