9 for SAS9 – Top Tips for SAS 9 Programmers Moving to SAS Viya

Transitioning from SAS9 to SAS Viya can be uncertain for SAS programmers. Whether your organization is making the move and you’re curious about your current SAS analytical workflows, or you're contemplating moving to SAS Viya and concerned about its impact on your SAS expertise and programs. The hesitation is understandable. As a fellow programmer, I recognize these concerns. However, there's reason to be excited! Viya offers traditional SAS code, enhanced capabilities, massively parallel processing, cloud-native, open source integration, and a variety of applications to add to your analytics processes.

Let's address those concerns, get excited, and delve into 9 essential insights for SAS 9 programmers making the transition to SAS Viya. All the programs are available in my GitHub repository.

1. Almost ALL of your SAS9 code runs on SAS Viya

First and foremost: Almost ALL your SAS9 code runs on SAS Viya. Think of the SAS Viya platform as a car with two engines. The first engine, the SAS Compute server, is designed to run traditional SAS code and provide the expected results. The SAS Compute server is equivalent to the traditional SAS9 engine (sometimes called the SAS workspace server or SPRE). Your DATA step, PROC MEANS, FREQ, favorite statistical procedures, SAS/ACCESS technology, ODS Graphics and more will produce the same results as they did in a SAS 9 environment. Don’t believe me? Go ahead - run this code in either SAS9 or SAS Viya. It doesn’t matter!

The code below uses the following SAS9 procedures and statements:

Macro variables

FILENAME statement

PROC HTTP

PROC IMPORT

PROC PRINT

PROC MEANS

PROC SQL

PROC FREQ

PROC FORMAT

DATA STEP

PROC SGPLOT

PROC LOGISTIC

PROC PLM

SAS9_Tips_Viya_01.sas

This program will download the home_equity.csv file from the Example Data Sets for the SAS Viya Platform documentation page and import it as a SAS table. Make sure to specify where to download the CSV file in your SAS environment by modifying the path macro variable. If your SAS environment is in lockdown mode you will have to manually download the CSV file and load it to your environment.

/**********************************/
/* 1 - Run SAS9 Code on SAS Viya! */
/**********************************/

/*****************************************/
/* a. REQUIRED - Specify the folder path */
/*****************************************/

/* This code will dynamically specify the project folder */
/* REQUIRED - SAS program must be saved to the location */
/* REQUIRED - Valid only in SAS Studio */
%let fileName = %scan(&_sasprogramfile,-1,'\/');
%let myPath = %sysfunc(tranwrd(&_sasprogramfile, &fileName,));
%put &=myPath;

/* You can also manually specify your path to the location you want to save the downloaded CSV file if the code above does not work */
%let path = &myPath; /*-----Modify your path here if necessary - Example path: C:/user/documents/ */

/* View the path to download the CSV file in the log */
%put &=path;

/*********************************/
/* b. Download CSV file from SAS */
/*********************************/

/* SAS Viya documentation data sets URL */
%let download_url = https://support.sas.com/documentation/onlinedoc/viya/exampledatasets/home_equity.csv;

/* Download CSV file from the internet and save the CSV file in SAS */
filename out_file "&path/home_equity.csv";
proc http
url="&download_url"
method="get"
out=out_file;
run;

/* Import the CSV file and create a SAS table in the WORK library */
proc import datafile="&path/home_equity.csv"
dbms=csv
out=work.home_equity
replace;
guessingrows=1000;
run;

/*********************************/
/* c. Run SAS9 in Viya! */
/*********************************/

/* Preview the SAS table */
proc print data=work.home_equity(obs=10);
run;

/* View column metatdata */
ods select Variables;
proc contents data=work.home_equity;
run;

/* View descriptive statistics */
proc means data=work.home_equity;
run;

/* View number of distinct values in specified columns */
proc sql;
select count(distinct BAD) as DistinctBAD,
count(distinct REASON) as DistinctREASON,
count(distinct JOB) as DistinctJOB,
count(distinct NINQ) as DistinctNINQ,
count(distinct CLNO) as DistinctCLNO,
count(distinct STATE) as DistinctSTATE,
count(distinct DIVISION) as DistinctDIVISION,
count(distinct REGION) as DistinctREGION
from work.home_equity;
quit;

/* View categorical column frequencies */
proc freq data=work.home_equity order=freq nlevels;
tables BAD REASON JOB NINQ CLNO STATE DIVISION REGION / plots=freqplot missing;
run;

/* View missing values in the table */

/* a. Create a format to group missing and nonmissing */
proc format;
value $missfmt
' '='Missing'
other='Not Missing';
value missfmt
. ='Missing'
other='Not Missing';
run;

/* b. Apply the format in PROC FREQ */
proc freq data=work.home_equity;
format _CHAR_ $missfmt.; /* apply format for the duration of this PROC */
tables _CHAR_ / missing missprint nocum nopercent;
format _NUMERIC_ missfmt.;
tables _NUMERIC_ / missing missprint nocum nopercent;
run;

/* Find the mean of the following columns to use to replace missing values using PROC SQL */
proc sql;
select round(mean(YOJ)) as MeanYOJ,
round(mean(MORTDUE)) as MeanMORTDUE,
round(mean(VALUE)) as MeanVALUE,
round(mean(DEBTINC)) as MeanDEBTINC
into :YOJmean trimmed,
:MORTDUEmean trimmed,
:VALUEmean trimmed,
:DEBTINCmean trimmed
from work.home_equity;
quit;
%put &=YOJmean &=MORTDUEmean &=VALUEmean &=DEBTINCmean;

/* Prepare the data */
data work.final_home_equity;
set work.home_equity;

/* Fix missing values */
if YOJ = . then YOJ = &YOJmean;
if MORTDUE = . then MORTDUE = &MORTDUEmean;
if VALUE = . then VALUE = &VALUEmean;
if DEBTINC = . then DEBTINC = &DEBTINCmean;

/* Round column */
DEBTINC = round(DEBTINC);

/* Format columns */
format APPDATE date9.;

/* Drop columns */
drop DEROG DELINQ CLAGE NINQ CLNO CITY;
run;

/* Check the final data for missing values */
proc freq data=work.final_home_equity;
format _CHAR_ $missfmt.; /* apply format for the duration of this PROC */
tables _CHAR_ / missing missprint nocum nopercent;
format _NUMERIC_ missfmt.;
tables _NUMERIC_ / missing missprint nocum nopercent;
run;

/* Preview final data */
proc print data=work.final_home_equity(obs=10);
run;

/* Create a visualization */
title height=14pt justify=left "Current vs Default Loans";
proc sgplot data=work.final_home_equity;
vbar BAD / datalabel;
run;
title;

/* Create a logistic regression model to predict bad loans */
proc logistic data=work.final_home_equity;
class REASON JOB / param=REFERENCE;
model BAD(event='1') = LOAN MORTDUE VALUE REASON JOB YOJ DEBTINC;
store mymodel;
run;

/* Score the model on the data */
proc plm restore=mymodel;
score data= work.final_home_equity
out=work.he_score predicted lclm uclm / ilink;
run;

/* Preview the scored data */
proc print data=work.he_score(obs=25);
run;

SAS9_Tips_Viya_01-result

The results demonstrate that the code produces the expected output, regardless of whether it is executed in SAS9 or SAS Viya.

2. Check hardcoded paths to your data

One common issue when moving from SAS9 to SAS Viya is any hardcoded paths to your data. If you are transitioning from SAS9 you will want to make sure you are pointing to where your data currently lives in the new Viya environment. This code uses the CSV file downloaded from previous code.

For example, let's pretend you were originally using SAS locally, and referencing the CSV file in your local directory. When moving to Viya, make sure the data you need is on the server, then simply modify the path. That's it!

SAS9_Tips_Viya_02.sas

/*****************************************/
/* 2 - Check hardcoded paths */
/*****************************************/

/* Old local path or SAS9 remote server path */
%let old_path = C:\workshop;

proc import datafile="C:/users/peter/home_equity.csv"
dbms=csv
out=work.new_table replace;
guessingrows=1000;
run;

/* New path to data in SAS Viya */
/* You can use the path macro variable from the previous program */
%let path = &path; /* ----- modify path to your data on the Viya server. Example - /new_viya_path/user */

proc import datafile="&path/home_equity.csv"
dbms=csv
out=work.new_table replace;
guessingrows=1000;
run;

3. Use the distributed CAS server for massively parallel processing (MPP)

Remember, I said SAS Viya is like a car with two engines? Well, the other engine is called Cloud Analytic Services (CAS). CAS is a massively parallel processing engine that processes memory-resident data. That’s right - you now have the ability to load data into memory for extended periods of time, as well as access to a cluster of machines designed for high-speed, parallel processing of big data.

The main difference to remember for CAS processing is that the data must be explicitly loaded into memory before it can be processed. Once loaded, the data remains available in-memory until removed, greatly reducing the impact of I/O in your processing. Here is an example of how to connect to the CAS server from your Compute server client, load a server-side file into memory, view the contents of the distributed in-memory CAS table, and then unload the CAS table.

SAS9_Tips_Viya_03.sas

/******************************************************************/
/* 3 - Loading data into memory in CAS for distributed processing */
/******************************************************************/

/***************************************************************/
/* a. Connect the Compute Server to the distributed CAS Server */
/***************************************************************/
cas conn;

/**********************************************/
/* b. View data sources connected to SAS Viya */
/**********************************************/

/* View available libraries (data sources) to the SAS Compute server */
libname _all_ list;

/* View available caslibs (data sources) connected to the CAS cluster */
caslib _all_ list;

/*********************************************************/
/* c. View available files in a caslib on the CAS server */
/*********************************************************/
/* The samples caslib is available by default. It's similar to the SASHELP library on the Compute server */

proc casutil;
list files incaslib = 'samples';
quit;

/********************************************************************************************/
/* d. Load a table into the distributed CAS server and view metadata of the in-memory table */
/********************************************************************************************/
proc casutil;

/* Explicitly load a server-side file into memory (files can be a database table, or other file formats like CSV,TXT, PARQUET and more) */
load casdata='RAND_RETAILDEMO.sashdat' incaslib = 'samples'
casout='RAND_RETAILDEMO' outcaslib = 'casuser';

/* View available in-memory tables in the Casuser caslib */
list tables incaslib = 'casuser';

/* View the contents of the in-memory table */
contents casdata='RAND_RETAILDEMO' incaslib = 'casuser';
quit;

/*****************************************/
/* e. Drop a distributed in-memory table */
/*****************************************/
proc casutil;
droptable casdata='RAND_RETAILDEMO' incaslib = 'casuser';
quit;

/*************************************/
/* f. Disconnect from the CAS server */
/*************************************/
cas conn terminate;

SAS9_Tips_Viya_03-result

The results display a range of information. In the section Detail Information for RAND_RETAILDEMO in Caslib CASUSER(Peter), it shows that the RAND_RETAILDEMO.sashdat file has been loaded into memory in CAS and distributed into blocks. This block distribution enables massively parallel processing of the data on CAS for faster processing.

For more information about the CAS server, check out the SAS® Cloud Analytic Services: Fundamentals documentation page.

4. Run DATA step code on the distributed CAS server

You can also run DATA step code on the distributed CAS server for massively parallel processing. This will dramatically increase the speed of your data preparation on big data. To run DATA step in CAS you must make a library reference to the Caslib on the CAS server. Then simply read from and write to CAS using the SAS DATA step. Most traditional SAS9 DATA step functions and statements are available in CAS.

Few considerations to make when running DATA step on the CAS server:

You must read a CAS table and write to a CAS table.

Not all SAS9 DATA step functions run on the CAS server. Check the latest documentation to determine if your function runs in CAS.

Not all SAS9 DATA step statements are supported in CAS. Check the latest documentation to determine if your statement runs in CAS.

SAS9_Tips_Viya_04.sas

/**********************************************************/
/* 4 - Run DATA step in on the distributed CAS server */
/**********************************************************/
/* NOTE: The data is small for training purposes */
/**********************************************************/

/***************************************************************/
/* a. Connect the Compute Server to the distributed CAS Server */
/***************************************************************/
cas conn;

/**************************************************/
/* b. Explicitly load a file into memory into CAS */
/**************************************************/

/* Load the demo home_equity.csv client-side file from the SAS Viya example data sets website into the CAS server */
filename out_file url "https://support.sas.com/documentation/onlinedoc/viya/exampledatasets/home_equity.csv";
proc casutil;
load file=out_file
casout='home_equity' outcaslib = 'casuser';
quit;

/* Confirm the table was loaded into CAS */
proc casutil;
/* View available in-memory distributed tables */
list tables incaslib = 'casuser';
quit;

/********************************************************************/
/* c. Create a library reference to a caslib using the CAS engine */
/********************************************************************/
libname casuser cas caslib = 'casuser';

/****************************/
/* d. Preview the CAS table */
/****************************/
title "Original Raw Data";
proc print data=casuser.home_equity(obs=10);
run;
title;

/*************************************************************************/
/* e. Run DATA step on the in-memory table in the distributed CAS server */
/* and create a new in-memory CAS table */
/*************************************************************************/

/* Prepare the data using the distributed CAS server */
data casuser.final_home_equity;
set casuser.home_equity end=end_of_thread; /* Use the END= option to view the processing by thread *.

/* Fix missing values with means */
if YOJ = . then YOJ = 9;
if MORTDUE = . then MORTDUE = 73761;
if VALUE = . then VALUE = 101776;
if DEBTINC = . then DEBTINC = 34;

/* Round column */
DEBTINC = round(DEBTINC);

/* Format columns */
format APPDATE date9.;

/* Drop columns */
drop DEROG DELINQ CLAGE NINQ CLNO CITY;

/* View number of rows processed on each thread (demo data, not all threads will be used) */
if end_of_thread=1 then
put 'Total Available Threads for Processing: ' _NTHREADS_
', Processing Thread ID: ' _THREADID_
', Total Rows Processed by Thread: ' _N_ ;
run;

/*********************************/
/* f. Preview the new CAS table */
/*********************************/
title 'Prepared CAS table';
proc print data=casuser.final_home_equity(obs=10);
run;
title;

/*****************************************************************/
/* Continue to the next program without disconnecting from CAS */
/*****************************************************************/

SAS9_Tips_Viya_04-result

The results show the new CAS table was successfully prepared as expected. Upon reviewing the log, we can see that this DATA step executed in parallel across multiple threads. Although the dataset in this example is relatively small for training purposes, the CAS server is generally used for larger data. Additionally, for the subsequent steps, let's leave the CAS table in memory and proceed with further processing without having to load it back into memory.

5. Use new distributed CAS procedures for MPP

SAS Viya supplies a wide array of new procedures designed to process data in CAS. The key is you must again have data loaded into memory on the distributed CAS server, create a library reference using the CAS engine to the caslib, then utilize the new procedure. Those resource intensive analytics you need to run? They’re really going to fly on SAS Viya! Check out the SAS Procedures and Corresponding CAS Procedures and Actions documentation for more information.

In this example, the data was loaded in the previous tip, and the library reference to the caslib is already set. So I can just continue running my analytical workflow!

SAS9_Tips_Viya_05.sas

The following CAS procedures are used:

PROC MDSUMMARY - Computes basic descriptive statistics for columns across all rows or within groups in parallel.

PROC FREQTAB - Provides tabulation and statistical analysis capabilities that are very similar to the capabilities of the FREQ procedure. The The main differences it the FREQTAB procedures in the distributed CAS server.

PROC CORRELATION - Provides functionality that is comparable to that of the HPCORR and CORR procedures in SAS9. The CORRELATION procedure is the next generation of the HPCORR procedure, and it was developed specifically for the CAS server.

PROC CARDINALITY - Determines a column's cardinality or limited cardinality on the CAS server.

PROC LOGSELECT - Provides logistic regression modeling functionality that is comparable to that of the HPLOGISTIC and LOGISTIC procedure. LOGSELECT processes data in in the CAS server.

PROC ASTORE - Scores the model from LOGSELECT on CAS.

/********************************************************************/
/* 5 - New distributed PROCS for the CAS server */
/********************************************************************/
/* NOTE: Continue processing the final_home_equity CAS table from */
/* the previous program. Once the data is loaded in-memory */
/* it stays in-memory until dropped or the CAS session ends. */
/********************************************************************/

/************************************/
/* a. Descriptive statistics in CAS */
/************************************/
proc mdsummary data=casuser.final_home_equity;
output out=casuser.home_equity_summary;
run;
proc print data=casuser.home_equity_summary;
run;

/************************************************/
/* b. Frequencies in the distributed CAS server */
/************************************************/
proc freqtab data=casuser.final_home_equity;
tables BAD REASON JOB STATE DIVISION REGION / plots=freqplot;
quit;

/************************************************/
/* c. Correlation in the distributed CAS server */
/************************************************/
proc correlation data=casuser.final_home_equity;
run;

/*********************************************************************************************************/
/* d. View the cardinality of the columns using CAS */
/*********************************************************************************************************/
/* The CARDINALITY procedure determines a variable’s cardinality or limited cardinality in SAS Viya. */
/* The cardinality of a variable is the number of its distinct values, and the limited cardinality of a */
/* variable is the number of its distinct values that do not exceed a specified threshold. */
/*********************************************************************************************************/
proc cardinality data=casuser.final_home_equity
outcard=casuser.home_equity_cardinality maxlevels=250;
run;
proc print data=casuser.home_equity_cardinality;
run;

/********************************************************/
/* e. Logistic regression in the distributed CAS server */
/********************************************************/
/* Demo: Logistic Regression Modeling Using the LOGSELECT Procedure in SAS Viya */
/* https://video.sas.com/detail/video/5334372288001/logistic-regression-modeling-using-the-logselect-procedure-in-sas-viya */

/* Run a logistic regression using the distributed CAS server */
proc logselect data=casuser.final_home_equity;
class REASON JOB / param=REFERENCE;
model BAD(event='1') = LOAN MORTDUE VALUE REASON JOB YOJ DEBTINC;
store out=casuser.mymodel;
run;

/* Score the data using your model */
proc astore;
score data=casuser.final_home_equity
rstore=casuser.mymodel
copyvars=BAD
out=casuser.home_equity_scored;
quit;

/* Preview the scored data */
proc print data=casuser.home_equity_scored(obs=10);
run;

/*****************************************************************/
/* Continue to the next program without disconnecting from CAS */
/*****************************************************************/

SAS9_Tips_Viya_05-result

The results display a range of information, including descriptive statistics, frequency values, visualizations, correlation coefficients, model details, and scoring information. All these analyses were processed on the distributed CAS server, showcasing just a subset of the numerous CAS-enabled procedures available.

6. Run SQL on the distributed CAS server for MPP

Want to run SQL on the distributed CAS server? Use FedSQL! Be aware PROC SQL does not run in CAS.

SAS9_Tips_Viya_06.sas

/********************************************************************/
/* 6 - Execute SQL in the distributed CAS server */
/********************************************************************/
/* NOTE: Continue processing the final_home_equity CAS table from */
/* the previous program. Once the data is loaded in-memory */
/* it stays in-memory until dropped or the CAS session ends. */
/********************************************************************/

/* To run SQL in the distributed CAS server you must use FedSQL with the sessref = option and the CAS session name */

/* Simple LIMIT */
proc fedsql sessref=conn;
select *
from casuser.final_home_equity
limit 10;
quit;

/* GROUP BY */
proc fedsql sessref=conn;
select BAD,
count(*) as TotalLoans,
mean(MORTDUE) as avgMORTDUE,
mean(YOJ) as avgYOJ
from casuser.final_home_equity
group by BAD;
quit;

/*****************************************************************/
/* Continue to the next program without disconnecting from CAS */
/*****************************************************************/

SAS9_Tips_Viya_06-result

The results demonstrate that you can utilize ANSI standard SQL on the distributed CAS server. However, it's important to note that PROC SQL won't execute on CAS. To leverage distributed processing, you need to use fedSQL instead.

7. Use the native CAS language (CASL) for additional data types and native CAS actions

If you are comfortable with object-oriented languages like Python, you’ll like CAS’ native language. CAS “speaks” CASL, with the work being done via CAS actions, which are optimized to run distributed on the CAS server. CAS actions perform a single task and are organized with other actions within an action set. You can think of actions as methods or functions. Using actions gives you the utmost control on your processing, and even faster results.

SAS9_Tips_Viya_07.sas

/**********************************************************************************/
/* 7 - Use the native CAS language (CASL) for additional data types and actions */
/**********************************************************************************/
/* NOTE: Continue processing the home_equity_final CAS table from */
/* the previous program. Once the data is loaded in-memory */
/* it stays in-memory until dropped or the CAS session ends. */
/**********************************************************************************/

/* Use CASL data types */
proc cas;
/* String */
myString = 'Peter Styliadis';
print myString;
describe myString;

/* Numeric */
myInt = 35;
print myInt;
describe myInt;

myDouble = 35.5;
print myDouble;
describe myDouble;

/* List */
myList = {'Peter', 'SAS', 37, 'Curriculum Development', {'Owen', 'Eva'}};
print myList;
describe myList;

/* Dictionary */
myDict = {Name='Peter', Age=37, Job='Curriculum Development', Children={'Owen', 'Eva'}};
print myDict;
describe myDict;
quit;

/* Use native CAS actions on the CAS server for MPP */
proc cas;
/* View available files in a caslib */
table.fileInfo / caslib = 'samples';

/* View available in-memory CAS tables in a caslib */
table.tableInfo / caslib = 'casuser';

/* Reference the CAS table using a dictionary */
tbl = {name="FINAL_HOME_EQUITY", caslib="casuser"};

/* Preview 10 rows of the CAS table */
table.fetch / table = tbl, to=10;

/* View the number of missing values and distinct values */
simple.distinct / table = tbl;

/* View descriptive statistics */
simple.summary / table = tbl;

/* View frequency values */
cols_for_freq = {'BAD','REASON','JOB'};
simple.freq / table = tbl, input = cols_for_freq;
quit;

/***********************************/
/* Disconnect from the CAS server */
/***********************************/
cas conn terminate;

New CASL data types

SAS9_Tips_Viya_07-result

The log and results show that the CAS procedures and actions ran successfully. Using CASL gives you additional capabilities through new data types like lists and dictionaries, as well as optimized CAS actions that run on the distributed CAS server. There are hundreds of new actions available. Check out the Actions by Name documentation for a list of available actions.

8. Use new SAS Studio point and click flows in Viya

SAS Viya also enables you to build flows in SAS Studio using custom programs or premade steps to help organize your analytic workflows. This is a great feature for programmers and point and click users alike! SAS Studio flows are similar to Enterprise Guide projects.

Check out the quick start video below for a quick demonstration!

Build Flows with SAS Studio | SAS Viya Quick Start Tutorial

9. Use Python in Viya

SAS Viya integrates open source technology across the analytics life cycle, enabling all types of SAS and open source users to collaborate. If you are a SAS programmer but dabble in Python, SAS Viya enables you to run Python code with the Python editor or PROC PYTHON in SAS Studio. You can also use the SAS Python SWAT package to process data in the massively parallel processing CAS engine using all Python.

Check out the resources below.

a. Getting Started with Python Integration to SAS® Viya® - Blog Series

b. Use Python Code in SAS Studio | SAS Viya Quick Start Tutorial

c. Use the Python SWAT Package on the SAS Viya Platform | SAS Viya Quick Start Tutorial

BONUS: Learn about point and click SAS Viya applications!

Ok one last one, not specifically for programmers so it doesn’t really count as 10, but if you want to get a glimpse of some of the point and click applications on the SAS Viya platform for creating dashboards, machine learning models, managing models, discovering information assets and more, check out the SAS Viya Quick Start Tutorials playlist!

Summary

We learned a lot here, but if you want a fundamentals course on making your SAS code run faster on SAS Viya check out the Accelerating SAS® Code on the SAS® Viya® Platform course! You can also check out the Accelerate Code in SAS Cloud Analytics | SAS Viya Quick Start Tutorial for a demonstration.

TLDR; let’s review!

The SAS Viya has two analytic engines, the SAS Compute server (SAS9) and Cloud Analytic Services (CAS). CAS is an in-memory massively parallel processing engine for all your big data and resource intensive programs with new optimized algorithms.

Almost all your SAS9 code will run on the SAS Compute server on the SAS Viya platform.

SAS Viya supplies a wide array of new optimized procedures designed specifically to process data in the massively parallel processing CAS server through the CAS LIBNAME engine.

The CAS server is typically reserved for larger data. Remember, just because you can use CAS doesn't mean you always should. Not all data needs massively parallel processing.

You can run SQL in SAS Viya using either the Compute server or the distributed CAS server. If you want to run SQL on the distributed CAS server, you must use FedSQL.

Did I mention almost all your SAS9 code will run on the SAS Compute server on the SAS Viya platform?

The SAS Viya platform is open, enabling the use of other languages like Python and R.

Viya contains a variety of point and click applications for any need in the analytical life cycle.

9 for SAS9 – Top Tips for SAS 9 Programmers Moving to SAS Viya was published on SAS Users.