Consultando usando o datepart de um carimbo de data/hora em um Proc SQL de passagem
-
21-12-2019 - |
Pergunta
Estou tentando usar a parte da data de um carimbo de data/hora em minha consulta where em um código SQL de passagem do DB2 abaixo.Tentei usar as funções date e datepart, mas não funcionou com este formato.Alguém sabe o nome da função para usar no mesmo código abaixo?
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;
Solução
Se você usar uma função no campo data e hora no DB2, o banco de dados não poderá usar seus índices (se esse campo estiver indexado).Isso ocorre porque os índices são (quase sempre) criados no próprio campo, e não no resultado do campo após ele ter sido processado por uma função.Isso vale para a maioria dos bancos de dados, não apenas para o DB2.
Em vez disso, o que você deseja fazer é fornecer valores de data e hora para o início e o final do dia e obter tudo entre eles.Para simplificar esse processo criei um formato chamado mysqldt.
.Originalmente, esse formato era para um banco de dados MySQL, mas o SQL Server e o DB2 usam os mesmos formatos, portanto também podem ser usados neles:
proc format;
picture mysqldt low-high = '''%Y-%0m-%0d %0H:%0M:%0S''' (datatype = datetime) ;
run ;
Quando esse formato estiver disponível, costumo usar variáveis macro.No topo do meu programa eu criaria uma variável macro onde especifico a data a ser usada em todo o relatório:
%let rpt_date = %sysfunc(mdy(1,12,2013));
Em seguida, eu criaria dois campos de data e hora representando o início e o fim do dia e os salvaria no formato necessário para a instrução 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;
Você então alteraria sua consulta para ficar assim:
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;
Dessa forma, não apenas seus índices serão usados em sua consulta, mas o SQL parecerá mais limpo e de leitura mais fácil, e você só precisará alterar a data do relatório em um único local (no topo do seu programa) se precisar executar novamente o seu relatório.
Outras dicas
Em geral, é necessário usar a sintaxe correta do DB2.Eu não conheço o DB2, mas este papel cobre isso bastante bem.Especificamente:
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')
Parece que sua consulta seria
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;
Este artigo da IBM parece sugerir que existem outros formatos além do carimbo de data / hora (que é o que está acima).Portanto, pode ser necessário usar um diferente dependendo do formato exato.
Eu acredito que você deve usar o literal de data SAS.Então:
where DATEPART(timestamp) > '12Jan2013'd