Querying using the datepart from a time stamp in a

2019-03-03 09:42发布

问题:

I am trying to use the date part of a time-stamp in my where query in a db2 pass-through proc SQL code below. I tried using date and datepart functions but it wont work with this format. Does anyone know the name of the function to use in the same code below?

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; 

回答1:

If you use a function on the datetime field in DB2 then the database won't be able to use it's indexes (if that field is indexed). This is because indexes are (almost always) created on the field itself, not the result of the field after it has been processed by a function. This holds true for the majority of databases not just DB2.

Instead, what you want to do is supply datetime values for the beginning of the day and for the end of the day and get everything inbetween them. To simplify this process I created a format called mysqldt.. Originally this format was for a mySQL database, but SQL server and DB2 both use the same formats so it can be used on those as well:

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

Once this format is available I tend to use macro variables. At the top of my program I would create a macro variable where I specify the date to use throughout the report:

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

I would then create two datetime fields representing the start of the day and the end of the day, and I would save them in the format that is needed for the SQL statement:

%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;

You would then change your query to look like this:

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; 

This way, not only are your indexes now used in your query, but the SQL looks cleaner and reads easier, and you only need to change the report date in a single place (at the top of your program) if you need to rerun your report.



回答2:

In general, you need to use the correct DB2 syntax. I don't know DB2, but this paper covers this fairly well. Specifically:

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')

So it looks like your query would be

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 from IBM seems to suggest that there are other formats other than timestamp (which is what above is). So you may need to use a different one depending on the exact format.



回答3:

I believe, you should use SAS-date literal. So:

 where DATEPART(timestamp) > '12Jan2013'd