Форматы даты SAS несовместимы с датой SQL Server
Я довольно новичок в SAS, и недавно мы перенесли некоторые из наших наборов данных SAS в таблицу SQL Server, но мы все еще используем SAS для нашего анализа. Я столкнулся с проблемой, когда SAS пытается ввести данные из таблицы SQL Server и проверить SAS, находится ли дата srv_edt между датами SAS dos_beg_dt1 и dos_end_dt1.
Когда SAS пытается сравнить даты, я получаю сообщение об ошибке: ОШИБКА: оператор предложения WHERE требует совместимых переменных.
Все dos_beg_dt1, dos_end_dt1 и srv_edt (формат даты SQL) "появляются" в формате гггг-мм-дд. Когда я помещаю srv_edt в таблицу SAS, она считывается как символьная дата. Поэтому я попытался изменить формат дат, и тогда я получу сообщение об ошибке: ОШИБКА: переменная srv_edt была определена как символьная, так и числовая. Я не могу найти правильный формат или функцию, чтобы заставить SAS выполнить сравнение, чтобы увидеть, находится ли srv_edt (SQL) между датами SAS dos_beg_dt1 и dos_end_dt1.
Код, который я использую, выглядит следующим образом:
libname sql odbc dsn=test schema=dbo;
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning),yymmdd10.);
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end),yymmdd10.);
data sample;
set sql.table;
where &dos_beg_dt1 <= srv_edt <= &dos_end_dt1;
run;
Для справки я использую SAS 9.2 для подключения через odbc к SQL Server 2008.
Любая помощь или совет будет принята с благодарностью.
3 ответа
SAS хранит и использует данные в качестве числовых переменных. Если вы не определили столбец srv_edt как столбец даты при переносе базы данных на SQL-сервер, все теперь будет обрабатываться правильно.
Я предполагаю, что в настоящее время и в будущем вы будете просто хранить таблицы на сервере SQL, а вся обработка будет выполняться в SAS.
У вас есть несколько вариантов.
1 / повторно перенастройте таблицы SAS, но идентифицируйте все столбцы даты, времени и даты и времени как просто числовые. Все они могут быть сохранены как 8-байтовые числа с плавающей точкой. Переменные даты также могут храниться (в SQL Server) с длинными целыми числами. Код должен будет немного измениться, чтобы макропеременные были числовыми.
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning));
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end));
2 / сохраните переменные даты, времени и даты и времени в формате SQL Server и измените тип данных столбца при использовании данных. (Обратите внимание, обратное будет необходимо на выходе). SQL Server представит переменные даты в виде строк (символов), поэтому ваше приведенное выше выражение должно быть:
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning));
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end));
data sample;
set sql.table;
where &dos_beg_dt1 <= (input(srv_edt, yymmdd10.0)) <= &dos_end_dt1;
Чтобы убедиться, что при использовании обработки SAS тип является числовым, что и делает функция ввода.
3 / сохраните переменные даты, времени и даты и времени в формате SQL Server и измените свою работу в соответствии с этим фактом. То есть для сравнения будут использоваться символьные данные, а для вывода необходимо будет создавать символьные данные. SQL Server представит переменные даты в виде строк (символов), поэтому ваше приведенное выше выражение должно быть:
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning), yymmdd10.);
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end), yymmdd10.);
data sample;
set sql.table;
where ("&dos_beg_dt1" <= srv_edt) and
(srv_edt <= "&dos_end_dt1");`
Обратите внимание на двойные кавычки " " обязательные окружающие макропеременные, так как это сравнение числовое.
Если столбец srv_edt отображается в вашем наборе данных SAS как символьная переменная, это означает, что это действительно символьная переменная или она была преобразована в символ используемым драйвером ODBC (возможно, из-за того, что собственный тип данных не поддерживается ODBC).
Вам лучше поменять это на сквозной запрос PROC SQL, если это возможно. Вам необходимо выяснить собственный синтаксис, который соответствует SAS intnx
функция (и я не могу помочь вам там). Как написано, вся таблица должна быть прочитана (потому что вы используете функцию SAS). Если вы используете сквозной запрос, SAS получит только те строки, которые соответствуют предложению whee.
В драйвере ODBC могут быть настройки, управляющие этим поведением. Я добавлю тэги ODBC и SQL Server к вашему вопросу; Вы можете получить больше "хитов".
SQL Server представил новые типы даты и даты и времени в SQL Server 2008 (ранее был только один тип для всех переменных даты / даты и времени). Это примечание об использовании предполагает, что вам нужно установить новый набор драйверов ODBC для SQL Server для SAS, чтобы правильно прочитать переменные даты. Предполагается, что он будет установлен нормально, если у вас есть инструменты SQL Server 2008 (например, SQL Server Management Studio) на компьютере, на котором выполняется соединение ODBC, но у вас может быть установлено несколько драйверов, и вам необходимо убедиться, что вы используете правильный.
Тем не менее, не является плохой идеей использовать сквозной SQL для передачи данных, поскольку это может упростить процесс извлечения (так как вам не нужно особо беспокоиться о драйвере ODBC). Обобщенная строка подключения
proc sql;
connect to odbc (required="driver=sql server native client 10.0;
Server=server;Trusted_Connection=Yes;DATABASE=database;");
create table X as select * from connection to odbc(... sql server native code here ...);
quit;
Из вашего вопроса это звучит так, как будто вы в большей степени человек SQL и можете сами построить запрос; если это не так, либо отредактируйте вопрос, чтобы включить этот запрос (и тогда ответит либо сотрудник SQL Server, либо я). В этом запросе можно использовать макропеременные SAS (т. Е. Для передачи текущей даты), если вы не заключаете их или запрос в одинарные кавычки.