2017-04-24 80 views
0

我与PROC SQL在SAS的工作和我的PROC SQL查询之一的行为非常奇怪:别名和组通过SAS PROC SQL语句

我有一个大的数据集(约1万行),其看起来是这样的:

apple_key profit price cost months date  
golden_d  0.03  12  4  3   01/12 
golden_d  0.03  8  0  2   01/12 
granny_s  0.05  15  5  5   02/12 
red_d  0.04  13  0  1   01/12 
golden_d  0.02  1  2  12   03/14 

在我运行下面的查询这组数据:

%let picking_date = 01/12; /* I simplify here - this part of my code definitely works */ 

proc sql; 
    CREATE TABLE output AS 
    SELECT 
     (CASE apple_key 
       WHEN "golden_d" THEN 1 
       WHEN "granny_s" THEN 2 
       WHEN "red_d" THEN 3 
     END) AS apple_id, 
     apple_key AS apple_name, 
     (CASE WHEN cost= 0 THEN 0 
      ELSE 1 
     END) AS cost_flag, 
     (CASE 
      WHEN CEIL(months/2) < 5 THEN CEIL(months/2) 
      ELSE 5 
     END) AS age, 
     "McDonalds" as farm, 
     sum(profit*price)/sum(price) as price_weighted_profit 
    FROM input_table 
    WHERE date = "&picking_date."d 
     AND price > cost 
     AND cost >= 0 
     AND cost >= 0 
    GROUP BY apple_id, apple_name, cost_flag, age, farm 
    ; 
run; 

当我运行此我GROUP BY声明不起作用。我为单个组获得了一堆条目 (其中apple_id,apple_name,cost_flag,年龄和农场都是相同的,但是我的聚合不起作用)。

但是,当我分别运行GROUP BY(如下所示)时,一切正常。我为每个组获得一个具有“价格加权利润”的条目:

proc sql; 
    CREATE TABLE output_tmp AS 
    SELECT 
     (CASE apple_key 
       WHEN "golden_d" THEN 1 
       WHEN "granny_s" THEN 2 
       WHEN "red_d" THEN 3 
     END) AS apple_id, 
     apple_key AS apple_name, 
     (CASE WHEN cost= 0 THEN 0 
      ELSE 1 
     END) AS cost_flag, 
     (CASE 
      WHEN CEIL(months/2) < 5 THEN CEIL(months/2) 
      ELSE 5 
     END) AS age, 
     "McDonalds" as farm 
    FROM input_table 
    WHERE date = "&picking_date."d 
     AND price > cost 
     AND cost >= 0 
     AND cost >= 0 
    ; 

    CREATE TABLE output AS 
    SELECT 
     apple_id, 
     apple_name, 
     cost_flag, 
     age, 
     farm, 
     sum(profit*price)/sum(price) as price_weighted_profit 
    FROM output_tmp 
    GROUP BY apple_id, apple_name, cost_flag, age, farm 
    ; 
quit; 

为什么会发生这种情况?我该如何解决它?这是让我有点疯狂......谢谢前面的帮助

+0

你想通过做一组来计算计数或总和? – Teja

+0

对不起。忘记将摘要函数语句移至第二个“create table”语句。现在应该是正确的。我在这里试图计算“price_weighted_profit” – MRR

+0

您希望从样本输入中得到什么结果?你得到什么输出? – Tom

回答

1

它不起作用,因为group by没有把总和(利润*价格)/总和(价格)语句作为聚合函数。它没有做到这一点,因为像年龄的别名,cost_flag等

反正下面是正确的查询: -

Proc sql; 
    CREATE TABLE output AS 
    SELECT 
      apple_id, 
      apple_name, 
      cost_flag, 
      age, 
      farm, 
      sum(profit*price)/sum(price) as price_weighted_profit 
     FROM 
     (
     SELECT 
      (CASE apple_key 
        WHEN "golden_d" THEN 1 
        WHEN "granny_s" THEN 2 
        WHEN "red_d" THEN 3 
      END) AS apple_id, 
      apple_key AS apple_name, 
      (CASE WHEN cost= 0 THEN 0 
       ELSE 1 
      END) AS cost_flag, 
      (CASE 
       WHEN CEIL(months/2) < 5 THEN CEIL(months/2) 
       ELSE 5 
      END) AS age, 
      "McDonalds" as farm 
     FROM input_table 
     WHERE date = "&picking_date."d 
      AND price > cost 
      AND cost >= 0 
      AND cost >= 0 

     ) a 
     GROUP BY apple_id, apple_name, cost_flag, age, farm; 
     quit; 

让我知道如果您有任何疑问

+0

非常感谢。这个解决了一切。只是为了确保我明白了:每次使用'AS'语句都会得到'alias'这些别名正在阻止GROUP BY'语句正确分组。你能帮我理解为什么会发生这种情况吗?如:为什么它不识别我的别名? – MRR

+1

是。你的理解是正确的。这是一个错误,或者我不知道SAS是如何工作的。得到它的生活 –

+0

听起来不错。非常感谢你的帮助! – MRR

0

经验法则: - 每当您在select子句中使用任何聚合函数,其余列应该是group by的一部分。在您发布的问题中,您发布的申请是总和(利润*价格)/总和(价格),但是没有导致问题的组。

Proc sql; 
    CREATE TABLE output AS 
     SELECT 
      (CASE apple_key 
        WHEN "golden_d" THEN 1 
        WHEN "granny_s" THEN 2 
        WHEN "red_d" THEN 3 
      END) AS apple_id, 
      apple_key AS apple_name, 
      (CASE WHEN cost= 0 THEN 0 
       ELSE 1 
      END) AS cost_flag, 
      (CASE 
       WHEN CEIL(months/2) < 5 THEN CEIL(months/2) 
       ELSE 5 
      END) AS age, 
      "McDonalds" as farm, 
      sum(profit*price)/sum(price) as price_weighted_profit 
     FROM input_table 
     WHERE date = "&picking_date."d 
      AND price > cost 
      AND cost >= 0 
      AND cost >= 0  
     GROUP BY apple_id, apple_name, cost_flag, age, farm; 
     quit; 
+0

嗨。感谢您的帮助,但如上所述,我在上述两个版本中都使用了“GROUP BY”。其中一人似乎没有工作就是没有工作。或者,也许我误解了你?你可以再详细一点吗? – MRR

+0

你能用上面我写的sql创建表吗? – Teja

0

我怀疑发生了什么是remerging。 SAS PROC SQL接受这样的代码:

proc sql; 
    select a.*, count(*) 
    from a; 

这并不汇总数据。相反,它将整个计数放在每一行上。换句话说,如果select中的密钥与group by不完全匹配,则根据group by密钥计算聚合函数,但结果会放在单独的行上。其他数据库使用窗口函数的子集来完成此操作。

在你的情况下,淹没并不明显。我认为存在关键的困惑,因为您在select中使用与原始数据中相同的名称。我的建议是更改别名,使其明确无误,并确保group by中的密钥是明确的。