【问题标题】:Querying using the datepart from a time stamp in a pass-through Proc SQL在传递 Proc SQL 中使用时间戳中的日期部分进行查询
【发布时间】:2014-06-04 16:18:40
【问题描述】:

我正在尝试在下面的 db2 pass-through proc SQL 代码中的 where 查询中使用时间戳的日期部分。我尝试使用 date 和 datepart 函数,但它不适用于这种格式。有谁知道下面相同代码中要使用的函数的名称?

PROC SQL; 
   connect to db2(ssid=smtng); 
     select *  from connection to db2 
         (select *  
             from ATable 
          where DATEPART(timestamp) > '12/01/2013'
   FOR READ ONLY WITH UR
    );
DISCONNECT FROM DB2;
QUIT; 

【问题讨论】:

    标签: function datetime sas proc-sql db2-connect


    【解决方案1】:

    如果您在 DB2 中的 datetime 字段上使用函数,那么数据库将无法使用它的索引(如果该字段已被索引)。这是因为索引(几乎总是)是在字段本身上创建的,而不是在字段被函数处理后的结果。这适用于大多数数据库,而不仅仅是 DB2。

    相反,您要做的是为一天的开始和一天的结束提供日期时间值,并获取它们之间的所有内容。为了简化这个过程,我创建了一个名为mysqldt. 的格式。最初这种格式用于 mySQL 数据库,但 SQL Server 和 DB2 都使用相同的格式,因此它也可以用于这些格式:

    proc format;
      picture mysqldt low-high = '''%Y-%0m-%0d %0H:%0M:%0S''' (datatype = datetime) ;
    run ;
    

    一旦这种格式可用,我倾向于使用宏变量。在我的程序顶部,我将创建一个宏变量,在其中指定要在整个报告中使用的日期:

    %let rpt_date = %sysfunc(mdy(1,12,2013));
    

    然后,我将创建两个日期时间字段,分别代表一天的开始和结束,并将它们保存为 SQL 语句所需的格式:

    %let sql_start = %sysfunc(dhms(&rpt_date, 0, 0, 0), mysqldt.);
    %let sql_end   = %sysfunc(dhms(&rpt_date,23,59,59), mysqldt.);
    
    %put &rpt_date &sql_start &sql_end;
    

    然后您将查询更改为如下所示:

    proc sql; 
      connect to db2(ssid=smtng); 
      select *  from connection to db2 
             (select *  
              from atable 
              where timestamp between &sql_start and &sql_end
              for read only with ur
        );
    quit; 
    

    这样,不仅您的索引现在在您的查询中使用,而且 SQL 看起来更清晰,更易于阅读,并且您只需在需要时在一个地方(在程序顶部)更改报告日期重新运行您的报告。

    【讨论】:

    • 嗯,这个格式可能需要拆分成两种格式,并给出微秒级精度。
    【解决方案2】:

    通常,您需要使用正确的 DB2 语法。我不了解 DB2,但this paper 很好地涵盖了这一点。具体来说:

    PROC SQL; 
    CREATE TABLE ONE AS SELECT * FROM CONNECTION TO DB2 
     (SELECT A.ID, A.NAME, B.AMOUNT, B.POSTDATE 
    FROM IDS A 
    INNER JOIN BANK B 
    ON A.ID = B.ID 
    WHERE POSTDATE BETWEEN '2007-01-01-00.00.00.000000' 
     AND '2007-09-30-23.59.59.999999')
    

    所以看起来你的查询应该是

    PROC SQL; 
       connect to db2(ssid=smtng); 
         select *  from connection to db2 
             (select *  
                 from ATable 
              where DATEPART(timestamp) > '2013-12-01-00.00.00.00000'
       FOR READ ONLY WITH UR
        );
    DISCONNECT FROM DB2;
    QUIT; 
    

    This article 来自 IBM 似乎暗示除了时间戳之外还有其他格式(如上所示)。因此,您可能需要根据具体格式使用不同的格式。

    【讨论】:

    • Rob 的回答可能比这更好;我将离开它,因为我在其中包含了一些希望有用的链接。
    • 谢谢.. 这个想法和 Rob 很相似。
    【解决方案3】:

    我相信,您应该使用 SAS 日期文字。所以:

     where DATEPART(timestamp) > '12Jan2013'd
    

    【讨论】:

    • 我认为情况并非如此。您需要在直通块中完全使用 DB2 代码。
    猜你喜欢
    • 2022-10-07
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多