使用带有Teradata的Proc sql在SAS中编写高效查询

编辑:这是一套更完整的代码,可以根据下面的答案准确显示正在进行的操作.
libname output '/data/files/jeff'
%let DateStart = '01Jan2013'd;
%let DateEnd = '01Jun2013'd;
proc sql;
CREATE TABLE output.id AS (
  SELECT disTINCT id
  FROM mydb.sale_volume AS sv
  WHERE sv.category IN ('a','b','c') AND
    sv.trans_date BETWEEN &DateStart AND &DateEnd
)
CREATE TABLE output.sums AS (
  SELECT id,SUM(sales)
  FROM mydb.sale_volue AS sv
  INNER JOIN output.id AS ids
    ON ids.id = sv.id
  WHERE sv.trans_date BETWEEN &DateStart AND &DateEnd
  GROUP BY id
)
run;

目标是根据类别成员资格在表中查询某些id.然后,我将这些成员的活动汇总到所有类别.

上述方法远比以下方法慢:

>运行第一个查询获取子集
>运行第二个查询,对每个ID求和
>运行内部连接两个结果集的第三个查询.

如果我理解正确,确保我的所有代码都完全通过而不是交叉加载可能更有效.

在昨天发布一个问题之后,一位成员建议我可以通过提出一个更具体针对我的情况的单独的绩效问题而受益.

我正在使用SAS Enterprise Guide编写一些程序/数据查询.我没有权限修改存储在“teradata”中的基础数据.

我的基本问题是在这种环境中编写高效的SQL查询.例如,我为一小部分ID查询一个大表(有数千万条记录).然后,我使用此子集再次查询更大的表:

proc sql;
CREATE TABLE subset AS (
  SELECT
    id
  FROM
    bigTable
  WHERE
    someValue = x AND
    date BETWEEN a AND b

)

这可以在几秒钟内完成,并返回90k ID.接下来,我想在大表中查询这组ID,然后出现问题.我希望随着时间的推移对ID的值进行求和:

proc sql;
CREATE TABLE subset_data AS (
  SELECT
    bigTable.id,SUM(bigTable.value) AS total
  FROM
    bigTable
  INNER JOIN subset
    ON subset.id = bigTable.id
  WHERE
    bigTable.date BETWEEN a AND b
  GROUP BY
    bigTable.id
)

无论出于何种原因,这需要很长时间.区别在于第一个查询标记’someValue’.第二个是查看所有活动,不管’someValue’中的内容是什么.例如,我可以标记每个订购披萨的顾客.然后我会查看订购披萨的所有客户的每次购买.

我对SAS并不太熟悉,所以我正在寻找有关如何更有效地做到这一点或加快速度的任何建议.我对任何想法或建议持开放态度,如果我能提供更多细节,请告诉我.我想我很惊讶第二个查询需要很长时间来处理.

解决方法

使用SAS访问teradata(或任何其他外部数据库)中的数据时,最重要的一点是SAS软件准备sql并将其提交到数据库.我们的想法是尝试让您(用户)从所有数据库特定的细节中解脱出来. SAS使用称为“implict pass-through”的概念来实现这一点,这意味着SAS将SAS代码转换为DBMS代码.发生的很多事情都是数据类型转换:SAS只有两种(只有两种)数据类型,数字和字符.

SAS处理为您翻译的事情,但这可能令人困惑.例如,我见过用VARCHAR(400)列定义的“懒惰”数据库表,其值永远不会超过一些较小的长度(如人名的列).在数据库中,这不是什么大问题,但由于SAS没有VARCHAR数据类型,因此每行创建一个宽度为400个字符的变量.即使使用数据集压缩,这也可能会使得到的SAS数据集不必要地变大.

另一种方法是使用“显式传递”,使用相关DBMS的实际语法编写本机查询.这些查询完全在DBMS上执行,并将结果返回给SAS(它仍然为您进行数据类型转换.例如,这是一个“传递”查询,它执行两个表的连接并创建一个SAS数据集作为结果:

proc sql;
   connect to teradata (user=userid password=password mode=teradata);
   create table mydata as
   select * from connection to teradata (
      select a.customer_id,a.customer_name,b.last_payment_date,b.last_payment_amt
      from base.customers a
      join base.invoices b
      on a.customer_id=b.customer_id
      where b.bill_month = date '2013-07-01'
        and b.paid_flag = 'N'
      );
quit;

请注意,括号内的所有内容都是本机teradata sql,并且连接操作本身在数据库中运行.

您在问题中显示的示例代码不是SAS / teradata程序的完整工作示例.为了更好地提供帮助,您需要显示真实的程序,包括任何库引用.例如,假设您的真实程序如下所示:

proc sql;
   CREATE TABLE subset_data AS
   SELECT bigTable.id,SUM(bigTable.value) AS total
   FROM   TDATA.bigTable bigTable
   JOIN   TDATA.subset subset
   ON     subset.id = bigTable.id
   WHERE  bigTable.date BETWEEN a AND b
   GROUP BY bigTable.id
   ;

这将指示先前分配的LIBNAME语句,SAS通过该语句连接到teradata.如果SAS甚至能够将完整查询传递给teradata,那么该WHERE子句的语法将非常相关. (您的示例未显示“a”和“b”所指的内容.SAS可以执行连接的唯一方法是将两个表拖回本地工作会话并在SAS服务器上执行连接.

我强烈建议的一件事是,您试图说服您的teradata管理员允许您在某个实用程序数据库中创建“驱动程序”表.我们的想法是,您将在teradata中创建一个包含要提取的ID的相对较小的表,然后使用该表执行显式连接.我相信你需要更正式的数据库培训才能做到这一点(比如如何定义一个合适的索引以及如何“收集统计数据”),但凭借这些知识和能力,你的工作才会飞翔.

我可以继续,但我会在这里停下来.我每天都广泛使用SAS和teradata,而我所说的是这个星球上最大的teradata环境之一.我喜欢两种编程.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...