{"id":2087,"date":"2015-09-18T00:00:00","date_gmt":"2015-09-14T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/sql-and-r\/"},"modified":"2021-05-03T14:02:04","modified_gmt":"2021-05-03T14:02:04","slug":"sql-and-r","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/sql-and-r\/","title":{"rendered":"SQL and R"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">The R platform and programming language supports a vast  array of data science techniq.&#160;With decades of history and over <a href=\"https:\/\/cran.r-project.org\/web\/packages\/\">7,000 packages<\/a> available  on CRAN it can be overwhelming to determine where to start.&#160;The <a href=\"https:\/\/www.simple-talk.com\/dotnet\/software-tools\/r-basics\/\">R-Basics<\/a>  and <a href=\"https:\/\/www.simple-talk.com\/dotnet\/software-tools\/visualizing-data-with-r\/\"> Visualizing Data with R<\/a> articles provide initial direction, but don&#8217;t go  into much detail about how to manipulate datasets within R.&#160; <\/p>\n<p>Fortunately, database professionals can be productive  quickly in this realm by leveraging their well-honed SQL skills.&#160; As you might expect, R supports the use of SQL to retrieve data from  centrally located relational databases.&#160;However,  several packages in R allow you to go beyond this realm and create and query  ad-hoc datasets on the fly in the midst of processing and analyzing data,  regardless of the data&#8217;s original source or final destination.&#160;In this article, we will look at several different approaches that  involve manipulating data with SQL using various R packages.<\/p>\n<p>There is a great deal of excitement regarding Microsoft&#8217;s  acquisition of Revolution Analytics that subsequently lead to R being integrated  into SQLServer 2016.&#160; SQLServer 2016  is available as a preview, but is still subject to changes before its official  release.&#160;Simple-talk is filled  with excellent articles that focus specifically on SQLServer.&#160;Once the details of the release are  finalized, you can expect more upcoming articles that uniquely address R as  implemented within SQLServer.&#160;But  since the final version of SQLServer is not yet available at this time, and  Simple-Talk has already covered <a href=\"https:\/\/www.simple-talk.com\/sql\/reporting-services\/making-data-analytics-simpler-sql-server-and-r\/\"> SQL Server Access from R<\/a>, this  article will demonstrate open source R in RStudio using SQL with other  relational databases.<\/p>\n<p>Part of the appeal of SQL is its availability in so many  different products.&#160; Most technical  professionals find themselves having to support and interact with a range of  technologies from both open source and commercial vendors. Despite  vendor-specific features and extensions, SQL is relatively standard across  implementations so its use as presented here will be familiar even to those who  currently work exclusively with SQLServer.&#160;This article will include references to two databases, SQLite, a small  freely available (public domain) database that many people use without even  knowing it and Oracle, a large commercial offering and competitor to SQLServer.&#160;The use of RODBC to access SQL Server has already been covered in the  Simple-Talk article <a href=\"https:\/\/www.simple-talk.com\/sql\/reporting-services\/making-data-analytics-simpler-sql-server-and-r\/\"> &#8216;<\/a><a href=\"https:\/\/www.simple-talk.com\/sql\/reporting-services\/making-data-analytics-simpler-sql-server-and-r\/\">Making  Data Analytics Simpler: SQL Server and R&#8217;<\/a><\/p>\n<h2>The RSQLite package<\/h2>\n<p>SQLite is the most widely <a href=\"http:\/\/www.sqlite.org\/mostdeployed.html\">deployed database<\/a> in the  world.&#160;It is included on Android,  iPhone and IOS devices and in Firefox, Chrome and Safari web browsers. <a href=\"https:\/\/www.sqlite.org\/famous.html\">Apple and Microsoft<\/a> include it  in their OSX and Windows 10 operating systems respectively and there are many  other products that include SQLite.&#160;It  is extremely easy to use, and can be of great value to developers who need a  database available but want to avoid the overhead often associated with  installing and configuring an external database.&#160;In this demonstration, we will download and install the RSQLite package  which will integrate SQLite into R running in RStudio.&#160; <\/p>\n<p>This example will show how data sets can seamlessly be  written into a SQLite database for subsequent analysis using familiar SQL  statements (the data in question pertains to automobile performance and fuel  efficiency).&#160;The dataset is included  with R during its initial installation.&#160;Since the included data is readily available within R, it is not  necessary to import the data from a spreadsheet or other external source.&#160;Such datasets are used in examples in R documentation, so they are  available within R during its initial installation, or are added along with code  when new packages are installed.<\/p>\n<p>The &#8220;mtcars&#8221; dataset is included by default in R.&#160;It consists of data from the 1974 Motor Trend US magazine (hence the &#8220;mt&#8221;  in the dataset name). The dataset describes fuel consumption and various aspects  of automobile design and performance for 32 automobiles.&#160;The help function will display a document that contains in-depth  description of the structure and contents of this dataset.<\/p>\n<pre>help(mtcars)\n<\/pre>\n<p>In order to access this dataset, it must first be loaded.  This &#8220;attaches&#8221; the dataset to the user&#8217;s current R session.&#160;&#160; <\/p>\n<pre>data(mtcars)\n<\/pre>\n<p>The dataset is represented in an object called a data frame  comprised of rows and columns.&#160;The  data frame is small enough to be easily perused in a spreadsheet-like display  using the <b> View<\/b> command.&#160; <\/p>\n<pre>View(mtcars)\n<\/pre>\n<p> <img loading=\"lazy\" decoding=\"async\" height=\"405\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2282-clip_image002.jpg\" width=\"605\" alt=\"2282-clip_image002.jpg\" \/><\/p>\n<p>If you want to remove the dataset from your session at a  later point to free up resources without exiting R, you can run the rm function.&#160;When you run this command, you will notice the mtcars variable listed in  the Environment pane will disappear.<\/p>\n<pre>rm(mtcars)\n<\/pre>\n<p>Within RStudio, the SQLite package must be installed unless  it had been previously installed.&#160;The  library function then can be called to load the package into the current working  environment. <\/p>\n<pre>install.packages(\"RSQLite\")\nlibrary(RSQLite)\n<\/pre>\n<p>Next we will create a new, empty SQLite database where we  can store the cars data.&#160;SQLite has  a rather simple data storage mechanism, all data for a database is installed  within a single file.&#160; The name of  this file must be specified when the database is created, and a connection to  this database is returned and used in subsequent commands to access and  manipulate the data and data structures within the database.<\/p>\n<pre>conn &lt;- dbConnect(SQLite(),'mycars.db')\n<\/pre>\n<p>This command creates a file named &#8220;mycars.db&#8221; in the  current working directory.&#160;If you  aren&#8217;t sure where this is, run <b> getwd()<\/b> to print  out your working directory and <b> setwd(&#8220;some-directory&#8221;)<\/b> to navigate to a  different directory.&#160;To actually  create a table, we will read data from the mtcars dataset and write it to the  new database.<\/p>\n<p>With the data loaded, and an active database connection to  the SQLite database, we can write the data by specifying the connection, the  name of the table, and the name of the data frame that contains the data to be  persisted.<\/p>\n<pre>dbWriteTable(conn, \"cars\", mtcars)\n<\/pre>\n<p>This simple statement created a table in the database with  data types analogous to the R data frame columns.&#160;The names of the table columns were based on the names of the columns in  the data frame.&#160;No complicated  CREATE TABLE statement was required with explicit definitions of column names,  data types, precision, storage configuration or other options. This level of  detail is unnecessary when the focus is on performing an ad-hoc exploratory data  analysis within R rather than defining a schema in a centralized database that  is intended for long-term use.&#160;  However, it is possible to run CREATE TABLE statements if you like to using  standard SQL DDL.<\/p>\n<pre>dbGetQuery(conn, 'CREATE TABLE test_table(id int, name text)')\n<\/pre>\n<p>SQLite, like other relational database stores metadata  describing the objects it contains.&#160;The tables in the database can be listed by a single function call.&#160; <\/p>\n<pre>dbListTables(conn)\n<\/pre>\n<p>Likewise, the field names for a given table can be listed  referencing the connection and the table name.<\/p>\n<pre>dbListFields(conn, \"cars\")\n<\/pre>\n<p>With a connection available, a database created and a table  populated with data, queries can now be executed using the <b>dbGetQuery<\/b>  function.<\/p>\n<pre>dbGetQuery(conn, \"SELECT * FROM cars WHERE mpg &gt; 20\")\n<\/pre>\n<p>Standard SQL syntax is available, though as in other  contexts where SQL is embedded in strings, you need to consider your usage of  quotes.&#160;Often it is simplest to  surround your queries with double quotes so that strings in a SQL statement can  be surrounded in single quotes.<b><\/b><\/p>\n<pre>dbGetQuery(conn, \"SELECT * FROM cars WHERE row_names LIKE 'Merc%'\")\n<\/pre>\n<p>As you might expect, modifying tables using SQL is also  possible using RSQLite.&#160;But there is  a shortcut if the case where a data frame is modified in the context of R with  the intention of overwriting a table previously created.&#160;The following example extracts the &#8220;make&#8221; of the car from the row name  where the make and model are concatenated.&#160; <\/p>\n<pre>mtcars$make &lt;- gsub(' .*$', '', rownames(mtcars))\n<\/pre>\n<p>This statement says in essence, &#8220;create a new column for  the data frame named &#8220;make&#8221; and populate each row&#8217;s make value by taking the row  name, finding the substring that starts with the first space and ends at the end  of the string, and removing that substring.&#8221;&#160;What remains is the first word in the string.&#160;The resulting data frame can be viewed to reveal the new make column  appended as the last column.<\/p>\n<p> <img loading=\"lazy\" decoding=\"async\" height=\"405\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2282-clip_image004.jpg\" width=\"606\" alt=\"2282-clip_image004.jpg\" \/><\/p>\n<p>The new column can now be used in queries like any of the  other columns.<\/p>\n<pre>&gt; dbGetQuery(conn, \"SELECT make, count(*) FROM cars GROUP BY make HAVING count(*) &gt; 1 ORDER BY 2 DESC, 1\")\n<\/pre>\n<p><\/p>\n<pre class=\"lang:c# theme:vs2012\">&#160;&#160;&#160; make count(*)\n1&#160;&#160; Merc&#160;&#160;&#160;&#160;&#160;&#160;&#160; 7\n2&#160;&#160; Fiat&#160;&#160;&#160;&#160;&#160;&#160;&#160; 2\n3 Hornet&#160;&#160;&#160;&#160;&#160;&#160;&#160; 2\n4&#160; Mazda&#160;&#160;&#160;&#160;&#160;&#160;&#160; 2\n5 Toyota&#160;&#160;&#160;&#160;&#160;&#160;&#160; 2\n<\/pre>\n<p>The RSQLite package makes it easy to take data from files,  spreadsheets, or other sources and quickly integrate it into a SQL accessible  database.&#160;It allows you to do a  great deal of data processing without requiring the additional time, resources  and effort needed to set up and maintain an external database.&#160;As convenient as this is, another package called sqldf simplifies this  type of processing even further.&#160;It  allows you to use SQL on data frames without giving any thought to setting up a  database at all. <\/p>\n<h2>The sqldf package<\/h2>\n<p>There is tremendous value in consistently using SQL (or  SQL-like) languages to explore and process data.&#160; Data Science professionals are frequently faced with the challenge of  integrating data from disparate data sources.&#160;Many of these are relational databases, and so require SQL to retrieve  data.&#160;In addition, NoSQL data  sources often support high level, declarative, SQL-like languages.&#160;For example, Hadoop users can use Hive and Pig.&#160;Cassandra provides access to data stored in column families (analogous to  relational tables) using Cassandra Query Language (CQL).&#160;In many cases data in arbitrary text files is structured enough to be  easily imported into a database, and a variety of utilities are commonly used to  make semi-structured data SQL accessible.&#160;Thinking about data in relational terms lends itself towards <a href=\"https:\/\/www.google.com\/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=4&amp;ved=0CC8QFjADahUKEwiRq-vbnO_HAhXOCo4KHbIeAN0&amp;url=http%3A%2F%2Fwww.jstatsoft.org%2Fv59%2Fi10%2Fpaper&amp;usg=AFQjCNFKII3Uv4EjwO-x6tt2F1zLHb_pkw&amp;bvm=bv.102537793,d.c2E\"> Tidy data formatting<\/a> that has value even outside of the relational realm.<\/p>\n<p>The sqldf package allows you to access data frames using  SQL.&#160;Regardless of where data  originates, it can be queried as long as it is contained within a data frame.&#160;This means that data can&#160; be  read in from a variety of data sources (delimited files, a web pages, web APIs,  a relational databases, NoSQL datasoures, etc) and subsequently queried and  manipulated as if it were all in a single relational database.&#160;To see how straightforward it is, open a new R Session, install the  package, load it and the mtcars data.<\/p>\n<pre>install.packages(\"sqldf\")\nlibrary(sqldf)\ndata(mtcars)\n<\/pre>\n<p>SQLDF allows you to query the data frame as if it were a  table and it is often as simple as passing the query as a string to the sqldf  function.<\/p>\n<pre>sqldf(\"SELECT * FROM mtcars WHERE mpg &gt; 20\")\n<\/pre>\n<p>If you are following along and executed this statement in  RStudio, the number of rows is correct, but the row names containing the name of  each car are missing.<\/p>\n<p> <img loading=\"lazy\" decoding=\"async\" height=\"342\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2282-clip_image006.jpg\" width=\"382\" alt=\"2282-clip_image006.jpg\" \/><\/p>\n<p>The reason is that row names are not standard columns and  are ignored by default by sqldf.&#160;To  include these rows in the output, specify <b> row.names=TRUE<\/b> when making the call.<\/p>\n<pre>sqldf(\"SELECT * FROM mtcars WHERE mpg &gt; 20\", row.names=TRUE)\n<\/pre>\n<p>Within R, there are many ways to create new data frames.&#160;The base language contains support, and packages like dplyr and reshape  are in common use.&#160;With sqldf, you  can bypass the use of all of this.&#160;In fact, the sqldf call itself returns a dataframe.&#160;With this in mind, you can do sequences of calls to sqldf to  incrementally process or summarize a data set.<\/p>\n<pre>df &lt;- sqldf(\"SELECT * FROM mtcars WHERE mpg &gt; 20\", row.names=TRUE)\n<\/pre>\n<p>The df object now contains a dataframe with the results of  the query.&#160;If you are going to  process a data frame in this way, you are better off making the row names an  ordinary column value.<\/p>\n<pre>df$make_model&lt;-row.names(df)\n<\/pre>\n<p>The new column is now available in the dataframe.&#160;And any result of a query, even if it varies widely from the original is  simply returned as a new data frame.<\/p>\n<pre>mpgSummary &lt;- sqldf(\"select avg(mpg) avg, min(mpg) min, max(mpg) max from df where make_model like 'Merc%'\")\n<\/pre>\n<p>The judicious use of aliases to have meaningful column  names in each new dataset will make it easier to do subsequent processing.&#160;Limiting yourself to alphanumeric characters for column names is  recommended.<\/p>\n<pre>mpgSummary\n<\/pre>\n<p><\/p>\n<pre class=\"lang:c# theme:vs2012\">&#160;&#160; avg&#160; min&#160; max\n1 23.6 22.8 24.4\n<\/pre>\n<p>The SQL used with sqldf will mirror that used by RSQLite  since behind the scenes, data is being written to SQLite tables for querying.&#160;&#160; <\/p>\n<p>The mtcars data set internally available in R is convenient  for examples.&#160;Although it is great  for quickly demonstrating or learning functionality, it is not sufficient for  real world applications where data must be retrieved from an external source.<\/p>\n<h2>File Imports<\/h2>\n<p>Before looking at making direct connections to a database,  it is important to recognize how simple and straightforward it is to read a  delimited file into RStudio.&#160;This  might be somewhat offensive to software developers who are accustomed to  creating applications that connect directly to databases using ODBC or JDBC.&#160; But R Users frequently need to integrate data from several different data  sources.&#160;Rather than expend time and  energy configuring specific packages and loading drivers, it be worth  considering exporting data from a query to a data file and reading the file into  RStudio.&#160;This practice can also  circumvent the need to run resource intensive SQL statements multiple times on a  database.<\/p>\n<p>Exporting data as CSV is a well supported option in many  relational database systems.&#160;SQLServer&#8217;s Management Studio has a &#8220;Results To Text&#8221; dialog where &#8220;Comma  delimited&#8221; can be specified as an output format.&#160;MySQL has a non-standard SQL SELECT clause to specify an OUTFILE clause.&#160;Many SQL Clients include an option to export data in this way. CSVs exported from databases can be  quickly validated using any spreadsheet program.<\/p>\n<p>R itself can import data from a wide variety of file  formats.&#160;This flexibility results in  additional complexity, specifically a long list of functions, many of which have  a large number of parameters that can be set to alter their behavior.&#160;RStudio masks this complexity and provides a simple dialog for importing  files.&#160; If you don&#8217;t have a CSV file &#160;handy, you can start by creating one  using R based on the mtcars dataset we saw earlier.<\/p>\n<pre>write.csv(mtcars, 'mtcars.csv')\n<\/pre>\n<p>Import this by selecting the &#8220;Import Dataset&#8221; option in the  Environment pane and choosing &#8220;From Text File&#8221;.<\/p>\n<p> <img loading=\"lazy\" decoding=\"async\" height=\"345\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2282-clip_image008.jpg\" width=\"401\" alt=\"2282-clip_image008.jpg\" \/><\/p>\n<p>A dialog is opened that provides a preview of how the data  will be imported based on the options selected.&#160;In most cases, uncheck stringsAsFactors and the defaults selected will  suffice.&#160; <\/p>\n<p> <img loading=\"lazy\" decoding=\"async\" height=\"491\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/2282-clip_image010.jpg\" width=\"606\" alt=\"2282-clip_image010.jpg\" \/><\/p>\n<p>As the data is imported, the actual R commands required to  read in and view the data are displayed inline in the console.&#160;The data is first read into R.<\/p>\n<pre>mtcars &lt;- read.csv(\"~\/Desktop\/r_art\/simple-talk-SQL-and-R\/mtcars.csv\", stringsAsFactors=FALSE)\n<\/pre>\n<p>The View function is then called on the new data frame to  display its contents.<\/p>\n<pre>View(mtcars)\n<\/pre>\n<p>If you wish, the read.csv command can be set aside and used  in a script making it unnecessary to import data interactively using the dialog  in the future.<\/p>\n<p>Because of data can often be conveniently be exported to  simple text files, they are frequently the simplest way to get data into  RStudio.&#160;This is not always the case  of course.&#160;At times, when working  with a relational database the amount of data being processed is prohibitive, or  the number of data frames to be created makes it unwieldy to manually export and  import multiple data files.&#160;Under  these circumstances, a direct connection to the database is the best option.&#160;There are a number of database specific packages that support direct  connections. Most of these packages are  based on the RJDBC package, and the RJDBC package can be used independently to  access a large variety of databases.<\/p>\n<h2>The RJava and RJDBC Package<\/h2>\n<p>JDBC is the Java analog to the ODBC standard that was  original developed by Microsoft.&#160;A  JDBC driver is software that enables a Java application to interact with a  specific database.&#160;The RJDBC package  therefore relies upon the RJava package and consequently on an underlying Java  installation on an R User&#8217;s machine.&#160;At times, the behavior of the Java Virtual Machine must be addressed to prevent  problems.&#160;For instance, if you  encounter OutOfMemoryExceptions, the solution is to increase the amount of  memory available to the JVM.<\/p>\n<pre>options( java.parameters = \"-Xmx4g\" )\n<\/pre>\n<p>Suffice it to say that there are a wide range of  configuration possibilities that can result in problems due to the myriad of  possible permutations of versions of R, Java, RJDBC, particular JDBC drivers and  a specific database.&#160;These are  virtually unheard of when using a vendor-specific version of R included with a  particular database (as is the case with OracleR and Microsoft SQLServer 2016),  but they are not uncommon when using RJDBC to make database connections.&#160;Again, the previous section describes exporting\/importing csvs as a  viable workaround worth considering if you encounter these sorts of issues.&#160;RJDBC problems are not unsolvable, just time-consuming.&#160;Projects that involve a one-time data dump don&#8217;t merit the attention  required to fix them.<\/p>\n<p>Install and load the RJDBC library.<\/p>\n<pre>install.packages(\"RJDBC\")\nlibrary(RJDBC)\n<\/pre>\n<p>This example uses the free <a href=\"http:\/\/www.oracle.com\/technetwork\/database\/database-technologies\/express-edition\/overview\/index.html\"> Oracle XE<\/a> database and a pre-installed demo account called HR.&#160;Note that in this case, the database installation itself is on a local  workstation, but completely external to R.&#160;Before running the R code, you must ensure that the HR user account is  available.&#160;From an operating system  prompt, connect as a user with DBA privileges.&#160; <\/p>\n<pre>sqlplus \/ as sysdba\n<\/pre>\n<p>Within SQL*Plus, unlock the HR account and set the password  to match the username.<\/p>\n<pre>alter user HR account unlock;\nalter user HR identified by HR;\n<\/pre>\n<p>RJDBC requires the use of a JDBC driver, in this case an  Oracle JDBC driver that was installed as part of <a href=\"http:\/\/www.oracle.com\/technetwork\/database\/features\/instant-client\/index-097480.html\"> Oracle&#8217;s Instant Client<\/a> is used.&#160;The code below includes a Java CLASSPATH that is specific to my personal  machine that must be modified to match your setup.&#160;It loads the JDBC driver which is then used to make a database  connection.<\/p>\n<pre>drv &lt;- JDBC(\"oracle.jdbc.OracleDriver\",\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; classPath=\"\/Users\/cas\/oracle\/product\/instantclient_11_2\/ojdbc6.jar\", \" \")\n<\/pre>\n<p>A connection is established using the loaded driver, a JDBC  URL, and the user and password associated with the HR account.<\/p>\n<pre>con &lt;- dbConnect(drv, \"jdbc:oracle:thin:@localhost:1521:XE\", \"HR\", \"HR\")\n<\/pre>\n<p>The connection is then passed in each call along with the  query.<\/p>\n<pre>hrTables&#160; &lt;- dbGetQuery(con, \"select * from tab\")\n\t<\/pre>\n<p>This query displays all of the tables available within the  HR user&#8217;s schema.<\/p>\n<pre>hrTables\n<\/pre>\n<p><\/p>\n<pre class=\"lang:c# theme:vs2012\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; TNAME TABTYPE CLUSTERID\n1&#160;&#160;&#160;&#160;&#160;&#160;&#160; COUNTRIES&#160;&#160; TABLE&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n2&#160;&#160;&#160;&#160;&#160; DEPARTMENTS&#160;&#160; TABLE&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n3&#160;&#160;&#160;&#160;&#160;&#160;&#160; EMPLOYEES&#160;&#160; TABLE&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n4 EMP_DETAILS_VIEW&#160;&#160;&#160; VIEW&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n5&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; JOBS&#160;&#160; TABLE&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n6&#160;&#160;&#160;&#160;&#160; JOB_HISTORY&#160;&#160; TABLE&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n7&#160;&#160;&#160;&#160;&#160;&#160;&#160; LOCATIONS&#160;&#160; TABLE&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n8&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;REGIONS&#160;&#160; TABLE&#160;&#160;&#160;&#160;&#160;&#160;&#160; NA\n<\/pre>\n<h1>Conclusion<\/h1>\n<p>There is plenty that is novel and perhaps foreign to a new  R user.&#160;But there is no reason to  abandon your hard-earned SQL skills.&#160;The RSQLite, SQLDF and RJDBC packages allow you to leverage your SQL skills  whether accessing external data or simply cleaning, filtering and modifying data  already loaded.&#160;When SQLServer is  released, the ease of integration of using the version R included will likely  enhance this synergy.&#160;R&#8217;s  flexibility in accessing other data sources will provide new opportunities to  create data-centric products and services that are far beyond what was  traditionally possible using SQL alone.<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Not only can you easily retrieve data from SQL Sources for analysis and visualisation in R, but you can also use SQL to create, clean, filter, query and otherwise manipulate datasets within R, using a wide choice of relational databases. There is no reason to abandon your hard-earned SQL skills!&hellip;<\/p>\n","protected":false},"author":177915,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4168,6011,4179,4150],"coauthors":[],"class_list":["post-2087","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-database","tag-software-tools","tag-source-control","tag-sql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2087","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/177915"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=2087"}],"version-history":[{"count":6,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2087\/revisions"}],"predecessor-version":[{"id":90790,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2087\/revisions\/90790"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=2087"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=2087"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=2087"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=2087"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}