Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要为一个变量SAS/SQL隐藏一些字段_Sql_Loops_Sas_Data Hiding_Anonymity - Fatal编程技术网

需要为一个变量SAS/SQL隐藏一些字段

需要为一个变量SAS/SQL隐藏一些字段,sql,loops,sas,data-hiding,anonymity,Sql,Loops,Sas,Data Hiding,Anonymity,我需要给一群人做一份报告,总结每个人的信息,但只透露每个报告将要报告的人的姓名。 我得到的是: 爱丽丝4 15%8 20% 鲍勃8 30%6 15% 卡罗尔4 15%8 20% 戴夫4 15%8 20% 艾琳4 15%8 20% 我想要的是: 爱丽丝的总结 爱丽丝4 15%8 20% 个人2 8 30%6 15% 个人3 4 15%8 20% 人员4 15%8 20% 人员5 4 15%8 20% 鲍勃的总结 人员1 4 15%8 20% 鲍勃8 30%6 15% 个人3 4 15%8 20%

我需要给一群人做一份报告,总结每个人的信息,但只透露每个报告将要报告的人的姓名。 我得到的是:

爱丽丝4 15%8 20% 鲍勃8 30%6 15%
卡罗尔4 15%8 20%
戴夫4 15%8 20%
艾琳4 15%8 20%

我想要的是:

爱丽丝的总结
爱丽丝4 15%8 20% 个人2 8 30%6 15%
个人3 4 15%8 20%
人员4 15%8 20%
人员5 4 15%8 20%

鲍勃的总结
人员1 4 15%8 20%
鲍勃8 30%6 15%
个人3 4 15%8 20%
人员4 15%8 20%
人员5 4 15%8 20%

等等

我已经尝试过几种方法,放弃了在person后面加数字,我最近的尝试如下:

proc sql;
create table Distinct_People
as select distinct(Name)
from have;
quit;

data People;
set Distinct_People end=no_more;
call symputx('Person'||left(_n_), Name);
if no_more then call symputx('NumPeople', _n_);
run;
quit;

%macro Loop;
%do j=1 %to &NumPeople;
%let Person=Person&j;
data want;
set have;
if Name="&&Person&j" then "&&Person&j";
else "Person";
run;
%end;
%mend Loop;
%Loop;
我知道我可能已经弄糟了上面的内容,但我真的需要弄清楚如何在procsql或数据步骤中使用SAS/SQL来实现这一点


谢谢大家!

我不知道您在宏中到底想做什么,也不知道您的结果到底出了什么问题,我可以在代码中发现3个错误:

一,

在循环中,每次执行循环时,都会覆盖数据集。在下一个循环中,您将再次访问覆盖的数据集。所以最后你只有一个数据集,因为每次只剩下人名时你都会覆盖它。所以你必须写
数据人&j
为每个人获取一个数据集

二,

人是什么?您以前没有在示例中定义它。据我所知,您必须使用
set have这里

三,

您忘了覆盖名称

 if Name="&&Person&j" then 
 name ="&&Person&j";
 else 
 name ="&Person";
或更简单的版本:

if Name ne "&&Person&j" then 
   name ="&Person";
四,

不是错误,但您应该使用
data\u null\u而不是
数据人,因为您使用此数据步骤只是为了生成一些宏变量,并且不再使用输出,因此无需在此创建新的数据集。并且在数据步骤过时后退出


编辑:

我今天进行了测试,这段代码对我来说绝对有效,如果您仍然出现错误,我猜您可能是输入错误,或者您的环境出了问题:

data have;

input name $ nr1 nr2 $ nr3 n4 $;
 datalines;
 Alice 4 15% 8 20%
Bob 8 30% 6 15%
Carol 4 15% 8 20%
Dave 4 15% 8 20%
Erin 4 15% 8 20% 
;
run;

proc sql;
create table Distinct_People
as select distinct(Name)
from have;
quit;

data _null_;
set Distinct_People end=no_more;
call symputx('Person'||left(_n_), Name);
if no_more then call symputx('NumPeople', _n_);
run;
quit;

%macro Loop;
%do j=1 %to &NumPeople;
data want&j;
set have;
if Name ne "&&Person&j" then name = cat("Person",_n_);
run;
%end;
%do j=1 %to &NumPeople;
proc print data=want&j; 
title1 " &&Person&j.'s Summary";
run;
%end;
%mend Loop;
%Loop;
结果:


我在
proc sql
中有一个使用联合查询的部分解决方案,其中包含子查询以获得匿名人员的姓名和号码

但正如您所注意到的,每个人都是手动输入到每个select查询中的。您可能不愿意为数据集中的200人而不是示例中显示的5人这样做。一种可能是运行insert查询,以镜像union的select查询:

proc sql;

create table AnonymousReport As
    SELECT CASE WHEN t1.name = 'Alice' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName, 
           t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Alice' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Bob' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
            t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Bob' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Carol' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
            t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Carol' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Dave' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
    t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Dave' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Erin' THEN t1.name ELSE CATS('Person', 
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
    t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Erin' As ReportToWhom
    FROM have t1;

quit;
一种可能的解决方案是跨数据集的所有行使用串联的insert SQL查询:

data concat;
    set have;
    length reptAll $3200;
    by name;
    retain reptAll;

    if first.name then reptAll = "";
    unionSQL = "INSERT INTO AnonymousReport (RptName, Col1Number, Col1Pct, Col2Number, Col2Pct, ReportToWhom)
        SELECT CASE WHEN t1.name = '" || name || "' THEN t1.name 
        ELSE CATS('Person', (SELECT count(name) + 1 From have t2 
        WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName, 
        t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, '" || name || "' As ReportToWhom
        FROM have t1";

    reptAll =  catx('; ', reptAll, unionSQL) ;

    call symput('query', reptAll);
    if last.name then output;
run;

在R中,我可以用它的
粘贴
/
for
循环/
应用
函数在几秒钟内完成这项工作,但SAS语法是另一个世界

那么代码就太离谱了。如何获得所需的结果?我被困在这里了。如前所述,我还将按个人输出每组数据。当您只做我提到的更改时,您会得到什么结果?到目前为止,您的代码看起来不错,只是一些逻辑错误,我得到了原始表“Want”。似乎无论我做什么,我都会把那张表拿回来。@s.Cross:发现另一个错误,将其添加到我的原始答案中(第3点)。但在代码中,如果不使用第1点,您仍然只能得到一个数据集,其中包含max j的结果。如果I include name=,返回错误180,表示name不符合顺序,而这看起来可以正常工作,kl78的回答正是我要找的!!谢谢你的帮助!
proc sql;

create table AnonymousReport As
    SELECT CASE WHEN t1.name = 'Alice' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName, 
           t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Alice' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Bob' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
            t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Bob' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Carol' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
            t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Carol' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Dave' THEN t1.name ELSE CATS('Person',
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
    t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Dave' As ReportToWhom
    FROM have t1

    UNION ALL

    SELECT CASE WHEN t1.name = 'Erin' THEN t1.name ELSE CATS('Person', 
           (SELECT count(name) + 1 From have t2 
            WHERE t2.name < t1.name AND t1.name ne t2.name)) END As RptName, 
    t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, 'Erin' As ReportToWhom
    FROM have t1;

quit;
RptName     Col1Number  Col1Pct Col2Number  Col2Pct    ReportToWhom
Alice       4           15%              8      20%    Alice
Person2     8           30%              6      15%    Alice
Person3     4           15%              8      20%    Alice
Person4     4           15%              8      20%    Alice
Person5     4           15%              8      20%    Alice
Person1     4           15%              8      20%    Bob
Bob         8           30%              6      15%    Bob
Person3     4           15%              8      20%    Bob
Person4     4           15%              8      20%    Bob
Person5     4           15%              8      20%    Bob
...
data concat;
    set have;
    length reptAll $3200;
    by name;
    retain reptAll;

    if first.name then reptAll = "";
    unionSQL = "INSERT INTO AnonymousReport (RptName, Col1Number, Col1Pct, Col2Number, Col2Pct, ReportToWhom)
        SELECT CASE WHEN t1.name = '" || name || "' THEN t1.name 
        ELSE CATS('Person', (SELECT count(name) + 1 From have t2 
        WHERE t2.name <= t1.name AND t1.name ne t2.name)) END As RptName, 
        t1.Col1Number, t1.Col1Pct, t1.Col2Number, t1.Col2Pct, '" || name || "' As ReportToWhom
        FROM have t1";

    reptAll =  catx('; ', reptAll, unionSQL) ;

    call symput('query', reptAll);
    if last.name then output;
run;
%macro runsql;
    proc sql;   
        &query; 
    quit;
%mend runsql;

%runsql;