├── .gitignore ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── SECURITY.md ├── _config.yml ├── _includes ├── footer.html ├── google-analytics.html ├── head.html ├── header-menutop.html ├── header.html ├── home.html ├── partials │ ├── install_homebrew.md │ ├── install_sql_server_linux_rhel.md │ ├── install_sql_server_linux_sles.md │ ├── install_sql_server_linux_ubuntu.md │ ├── install_sql_server_mac.md │ ├── install_sql_server_windows.md │ ├── install_sql_server_windows_ML.md │ ├── install_sqlcmd_linux_rhel.md │ ├── install_sqlcmd_linux_sles.md │ ├── install_sqlcmd_linux_ubuntu.md │ ├── install_sqlcmd_mac.md │ ├── install_sqlcmd_windows.md │ └── step3 │ │ ├── mssql.md │ │ ├── note.md │ │ └── title.md ├── questions.html ├── resources.html └── scripts.html ├── _layouts ├── default-menutop.html ├── default.html ├── home.html ├── page-steps.html └── page.html ├── _sass ├── base │ ├── _fonts.scss │ ├── _functions.scss │ ├── _globals.scss │ ├── _states.scss │ ├── _utilities.scss │ ├── _variables.scss │ ├── functions │ │ └── _image.scss │ └── mixins │ │ ├── _fonts.scss │ │ └── _medias.scss ├── components │ ├── _disqus.scss │ ├── _footer.scss │ ├── _header.scss │ ├── _home.scss │ ├── _main.scss │ ├── _menu.scss │ ├── _menutop.scss │ ├── _new.scss │ ├── _page-steps.scss │ ├── _questions.scss │ └── _resources.scss ├── minima.scss └── vendor │ ├── _normalize.scss │ ├── _prism.scss │ └── _reset.scss ├── application ├── __init__.pyc └── views.pyc ├── assets ├── images │ ├── Thumbs.db │ ├── VSCode_Extension.png │ ├── award.png │ ├── bg.png │ ├── channel9.png │ ├── hero-image.png │ ├── hero-image_sub.png │ ├── menu │ │ ├── csharp.png │ │ ├── java.png │ │ ├── node.png │ │ ├── php.png │ │ ├── python.png │ │ └── r-logo.png │ ├── micro-logo.png │ ├── newsletter.png │ └── r-logo.png └── scripts │ ├── prism.js │ └── steps.js ├── index.md └── pages ├── R ├── customerclustering │ ├── step-1.md │ ├── step-2.md │ └── step-3.md └── rentalprediction │ ├── step-1.md │ ├── step-2.md │ └── step-3.md └── python ├── customerclustering ├── step-1.md ├── step-2.md └── step-3.md └── rentalprediction ├── step-1.md ├── step-2.md └── step-3.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby "2.2.2" 3 | gem "kramdown" 4 | gem "bundler" 5 | gem "jekyll", "3.4.3" 6 | gem "jekyll-redirect-from" 7 | gem "minima", "2.1.1" 8 | gem "jekyll-feed" 9 | # Hello! This is where you manage which Jekyll version is used to run. 10 | # When you want to use a different version, change it below, save the 11 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 12 | # 13 | # bundle exec jekyll serve 14 | # 15 | # This will help ensure the proper Jekyll version is running. 16 | # Happy Jekylling! 17 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.5.1) 5 | public_suffix (~> 2.0, >= 2.0.2) 6 | colorator (1.1.0) 7 | ffi (1.9.18) 8 | ffi (1.9.18-x64-mingw32) 9 | forwardable-extended (2.6.0) 10 | jekyll (3.4.3) 11 | addressable (~> 2.4) 12 | colorator (~> 1.0) 13 | jekyll-sass-converter (~> 1.0) 14 | jekyll-watch (~> 1.1) 15 | kramdown (~> 1.3) 16 | liquid (~> 3.0) 17 | mercenary (~> 0.3.3) 18 | pathutil (~> 0.9) 19 | rouge (~> 1.7) 20 | safe_yaml (~> 1.0) 21 | jekyll-feed (0.9.2) 22 | jekyll (~> 3.3) 23 | jekyll-redirect-from (0.12.1) 24 | jekyll (~> 3.3) 25 | jekyll-sass-converter (1.5.0) 26 | sass (~> 3.4) 27 | jekyll-watch (1.5.0) 28 | listen (~> 3.0, < 3.1) 29 | kramdown (1.13.2) 30 | liquid (3.0.6) 31 | listen (3.0.8) 32 | rb-fsevent (~> 0.9, >= 0.9.4) 33 | rb-inotify (~> 0.9, >= 0.9.7) 34 | mercenary (0.3.6) 35 | minima (2.1.0) 36 | jekyll (~> 3.3) 37 | pathutil (0.14.0) 38 | forwardable-extended (~> 2.6) 39 | public_suffix (2.0.5) 40 | rb-fsevent (0.9.8) 41 | rb-inotify (0.9.8) 42 | ffi (>= 0.5.0) 43 | rouge (1.11.1) 44 | safe_yaml (1.0.4) 45 | sass (3.4.23) 46 | thread_safe (0.3.6) 47 | tzinfo (1.2.3) 48 | thread_safe (~> 0.1) 49 | tzinfo-data (1.2017.2) 50 | tzinfo (>= 1.0.0) 51 | 52 | PLATFORMS 53 | ruby 54 | x64-mingw32 55 | 56 | DEPENDENCIES 57 | jekyll (= 3.4.3) 58 | jekyll-feed (~> 0.6) 59 | jekyll-redirect-from 60 | minima (~> 2.0) 61 | tzinfo-data 62 | 63 | RUBY VERSION 64 | ruby 2.3.3p222 65 | 66 | BUNDLED WITH 67 | 1.14.6 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # SQL Server Tutorials Documentation Contributor Guide 3 | You've found the GitHub repository that houses the source for the SQL Server ML tutorials that is published on [http://aka.ms/mlsqldev](aka.ms/mlsqldev). 4 | 5 | 6 | ## Contribute to SQL Server tutorials 7 | Firstly, thank you for your interest in contributing to our tutorials. We use Jekyll + Markdown for our documentation. To contribute, simply make a PR with changes in the Markdown files/new Markdown files. We will review it within 24 hours. 8 | 9 | ## Repository organization 10 | The content in the repository follows the standard Jekyll folder structure: 11 | 12 | ### \pages 13 | The *\pages* folder contains the documentation articles formatted as markdown files with an *.md* extension for each tutorial. 14 | 15 | ### \_includes 16 | This folder contains reusable content sections to be included in one or more articles. This folder also contains base html files that are used accross the site. 17 | 18 | ### \_sass 19 | This folder contains the css files used the style the website 20 | 21 | ### \assets 22 | This folder contains images and js scripts used in the tutorials website 23 | 24 | 25 | ## Use GitHub, Git, and this repository 26 | For information about how to contribute, how to use the GitHub UI to contribute small changes, and how to fork and clone the repository for more significant contributions, see [Install and set up tools for authoring in GitHub](contributor-guide/tools-and-setup.md). 27 | 28 | If you install GitBash and choose to work locally, the steps for creating a new local working branch, making changes, and submitting the changes back to the main branch are listed in [Git commands for creating a new article or updating an existing article](contributor-guide/git-commands-for-master.md) 29 | 30 | ### Branches 31 | We recommend that you create local working branches that target a specific scope of change. Each branch should be limited to a single concept/article both to streamline work flow and reduce the possibility of merge conflicts. The following efforts are of the appropriate scope for a new branch: 32 | 33 | * A new article (and associated images) 34 | * Spelling and grammar edits on an article. 35 | * Applying a single formatting change across a large set of articles (e.g. new copyright footer). 36 | 37 | ## How to use markdown to format your topic 38 | All the articles in this repository use GitHub flavored markdown. Here's a list of resources. 39 | 40 | * [Markdown basics](https://help.github.com/articles/markdown-basics/) 41 | * [Printable markdown cheatsheet](./contributor-guide/media/documents/markdown-cheatsheet.pdf?raw=true) 42 | 43 | ## Article metadata 44 | Article metadata enables certain functionalities, such as author attribution, contributor attribution, breadcrumbs, article descriptions, and SEO optimizations as well as reporting Microsoft uses to evaluate the performance of the content. So, the metadata is important! [Here's the guidance for making sure your metadata is done right](contributor-guide/article-metadata.md). 45 | 46 | ## Microsoft Open Source Code of Conduct 47 | 48 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 49 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 50 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Site settings 2 | # Access it in the templates via {{ site.myvariable }}. 3 | title: Get Started with SQL Server Machine Learning Services 4 | description: > 5 | Get Started with SQL Server Machine Learning Services 6 | url: "https://microsoft.github.io/sql-ml-tutorials/" 7 | 8 | disqus: 9 | shortname: sqlchoice 10 | 11 | gitter: https://gitter.im/Microsoft/mssql-developers 12 | 13 | steps: 14 | 1: Set up your environment 15 | 2: Create your ML script using $$ 16 | 3: Deploy your ML script with SQL Server 17 | 18 | menu: 19 | R: 20 | logo: r-logo.png 21 | pages: 22 | Predict ski rentals: R/rentalprediction 23 | Perform customer clustering: R/customerclustering 24 | 25 | Python: 26 | logo: python.png 27 | pages: 28 | Predict ski rentals: python/rentalprediction 29 | Perform customer clustering*: python/customerclustering 30 | 31 | 32 | resources: 33 | sqlserver-R: 34 | pre: Check out what's new with 35 | text: SQL Server + R on Channel 9 36 | link: https://channel9.msdn.com/Events/Connect/2016/151 37 | condition: R 38 | sqlserver-csharp: 39 | pre: Check out what's new with 40 | text: SQL Server + C# on Channel 9 41 | link: https://channel9.msdn.com/Events/Connect/2016/151 42 | condition: C# 43 | sqlserver-java: 44 | pre: Check out what's new with 45 | text: SQL Server + Java on Channel 9 46 | link: https://channel9.msdn.com/Events/Connect/2016/152 47 | condition: Java 48 | sqlserver-node: 49 | pre: Check out what's new with 50 | text: SQL Server + Node.js on Channel 9 51 | link: https://channel9.msdn.com/Events/Connect/2016/160 52 | condition: Node.js 53 | sqlserver-php: 54 | pre: Check out what's new with 55 | text: SQL Server + PHP on Channel 9 56 | link: https://channel9.msdn.com/Events/Connect/2016/182 57 | condition: PHP 58 | sqlserver-py: 59 | pre: Check out what's new with 60 | text: SQL Server + Python on Channel 9 61 | link: https://channel9.msdn.com/Events/Connect/2016/189 62 | condition: Python 63 | github: 64 | pre: Browse more SQL Server code samples on our 65 | text: GitHub repository 66 | link: https://github.com/Microsoft/sql-server-samples/tree/master/samples/features 67 | sql17: 68 | pre: Learn more about 69 | text: SQL Server 2017 70 | link: https://www.microsoft.com/en-us/sql-server/sql-server-2017 71 | sourcecodepy: 72 | pre: Get the sample code for this tutorial 73 | text: here 74 | link: https://github.com/Microsoft/sql-server-samples/tree/master/samples/features/machine-learning-services/python/getting-started/rental-prediction 75 | condition: Python 76 | sourcecodeR: 77 | pre: Get the sample code for this tutorial 78 | text: here 79 | link: https://github.com/Microsoft/sql-server-samples/tree/master/samples/features/r-services/getting-started 80 | condition: R 81 | 82 | # Build settings 83 | markdown: kramdown 84 | theme: minima # we are extending it 85 | exclude: 86 | - Gemfile 87 | - Gemfile.lock 88 | - README.md 89 | 90 | gems: 91 | - jekyll-redirect-from 92 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /_includes/google-analytics.html: -------------------------------------------------------------------------------- 1 | 2 | 40 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% if page.title and page.language %} 9 | {{ page.language | escape }} {{ page.title | escape }} 10 | {% else if page.title %} 11 | SQL Server ML Services - Get Started 12 | {% else %} 13 | SQL Server ML Services - Get Started 14 | {% endif %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | {% include google-analytics.html %} 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /_includes/header-menutop.html: -------------------------------------------------------------------------------- 1 | 49 | -------------------------------------------------------------------------------- /_includes/header.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/home.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | 5 |

6 | 7 | 8 | 9 | Check out some of our other getting started tutorials! 10 | 11 | 12 | 13 | 14 | 15 | 28 | 29 | 30 | Don't see a machine learning scenario you were looking for? Join the conversation on Gitter. 31 |
32 |
33 | Contribute to these tutorials on GitHub! 34 |
35 |
36 | -------------------------------------------------------------------------------- /_includes/partials/install_homebrew.md: -------------------------------------------------------------------------------- 1 | ```terminal 2 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 3 | ``` -------------------------------------------------------------------------------- /_includes/partials/install_sql_server_linux_rhel.md: -------------------------------------------------------------------------------- 1 | Note: To ensure optimal performance of SQL Server, your machine should have at least 4 GB of memory. 2 | 3 | 1. Register the Microsoft Linux repository 4 | 5 | ```terminal 6 | sudo su 7 | curl https://packages.microsoft.com/config/rhel/7/mssql-server.repo > /etc/yum.repos.d/mssql-server.repo 8 | exit 9 | ``` 10 | 11 | 2. Install SQL Server 12 | 13 | ```terminal 14 | sudo yum update 15 | sudo yum install mssql-server 16 | ``` 17 | 18 | 3. Setup your SQL Server 19 | 20 | ```terminal 21 | sudo /opt/mssql/bin/mssql-conf setup 22 | ``` 23 | 24 | ```results 25 | Microsoft(R) SQL Server(R) Setup 26 | 27 | To abort setup at anytime, press Ctrl-C. 28 | 29 | The license terms for this product can be downloaded from http://go.microsoft.com/fwlink/?LinkId=746388 and 30 | found in /usr/share/doc/mssql-server/LICENSE.TXT. 31 | 32 | Do you accept the license terms? If so, please type YES: 33 | Please enter a password for the system administrator (SA) account: 34 | Please confirm the password for the system administrator (SA) account: 35 | ``` 36 | 37 | You now have SQL Server running locally on RHEL machine! Check out the next section to continue installing prerequisites. 38 | -------------------------------------------------------------------------------- /_includes/partials/install_sql_server_linux_sles.md: -------------------------------------------------------------------------------- 1 | Note: To ensure optimal performance of SQL Server, your machine should have at least 4 GB of memory. 2 | 3 | 1. Register the Microsoft Linux repository and add they keys 4 | 5 | ```terminal 6 | sudo zypper addrepo -fc https://packages.microsoft.com/config/sles/12/mssql-server.repo 7 | sudo zypper --gpg-auto-import-keys refresh 8 | ``` 9 | 10 | 2. Install SQL Server 11 | 12 | ```terminal 13 | sudo zypper update 14 | sudo zypper install mssql-server 15 | ``` 16 | 17 | 3. Setup your SQL Server 18 | 19 | ```terminal 20 | sudo /opt/mssql/bin/mssql-conf setup 21 | ``` 22 | 23 | ```results 24 | Microsoft(R) SQL Server(R) Setup 25 | 26 | To abort setup at anytime, press Ctrl-C. 27 | 28 | The license terms for this product can be downloaded from http://go.microsoft.com/fwlink/?LinkId=746388 and 29 | found in /usr/share/doc/mssql-server/LICENSE.TXT. 30 | 31 | Do you accept the license terms? If so, please type YES: 32 | Please enter a password for the system administrator (SA) account: 33 | Please confirm the password for the system administrator (SA) account: 34 | ``` 35 | 36 | You now have SQL Server running locally on RHEL machine! Check out the next section to continue installing prerequisites. 37 | -------------------------------------------------------------------------------- /_includes/partials/install_sql_server_linux_ubuntu.md: -------------------------------------------------------------------------------- 1 | Note: To ensure optimal performance of SQL Server, your machine should have at least 4 GB of memory. 2 | If you need to get Ubuntu, check out the Ubuntu Downloads website. 3 | 4 | 1. Register the Microsoft Linux repositories and add they keys 5 | 6 | ```terminal 7 | sudo su 8 | curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - 9 | curl https://packages.microsoft.com/config/ubuntu/16.04/mssql-server.list > /etc/apt/sources.list.d/mssql-server.list 10 | sudo /opt/mssql/bin/mssql-conf setup 11 | exit 12 | ``` 13 | 14 | 2. Install SQL Server 15 | 16 | ```terminal 17 | sudo apt-get update 18 | sudo apt-get install mssql-server 19 | ``` 20 | 21 | ```results 22 | Reading package lists... Done 23 | Building dependency tree 24 | Reading state information... Done 25 | The following NEW packages will be installed: 26 | mssql-server 27 | ... 28 | Unpacking mssql-server ... 29 | Setting up mssql-server ... 30 | ``` 31 | 32 | 3. Setup your SQL Server 33 | 34 | ```terminal 35 | sudo /opt/mssql/bin/mssql-conf setup 36 | ``` 37 | 38 | ```results 39 | Microsoft(R) SQL Server(R) Setup 40 | 41 | To abort setup at anytime, press Ctrl-C. 42 | 43 | The license terms for this product can be downloaded from http://go.microsoft.com/fwlink/?LinkId=746388 and 44 | found in /usr/share/doc/mssql-server/LICENSE.TXT. 45 | 46 | Do you accept the license terms? If so, please type YES: 47 | Please enter a password for the system administrator (SA) account: 48 | Please confirm the password for the system administrator (SA) account: 49 | ``` 50 | 51 | You now have SQL Server running locally on Ubuntu! Check out the next section to continue installing prerequisites. 52 | -------------------------------------------------------------------------------- /_includes/partials/install_sql_server_mac.md: -------------------------------------------------------------------------------- 1 | 1. In order to run SQL Server on your Mac you need to [install Docker](https://docs.docker.com/engine/installation/mac/). 2 | 2. Configure at least 4GB of memory for your Docker environment, also consider adding multiple cores if you want to evaluate performance. You can do this in the [Docker Preferences](https://docs.docker.com/docker-for-mac/#preferences) option on the menu bar. 3 | 3. Next, start a new **Terminal prompt** and use the following commands to download and start the **SQL Server on Linux** Docker image. Make sure to use a strong password with special characters. 4 | 5 | ```terminal 6 | sudo docker pull microsoft/mssql-server-linux 7 | docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=yourStrong(!)Password' -p 1433:1433 -d microsoft/mssql-server-linux 8 | ``` 9 | 10 | > You now have SQL Server running locally in Docker! Check out the next section to continue installing prerequisites. 11 | -------------------------------------------------------------------------------- /_includes/partials/install_sql_server_windows.md: -------------------------------------------------------------------------------- 1 | 1. If you don’t have SQL Server 2016 Developer (or above) installed, click [**here**](http://go.microsoft.com/fwlink/?LinkID=799009) to download the SQL Server exe 2 | 2. Run it to start the SQL installer 3 | 3. Click **Basic** in *Select an installation type* 4 | 4. Click **Accept** after you have read the license terms 5 | 5. (Optional) if you need to, you can choose a custom installation location for SQL Server 6 | 6. Click **Install** to proceed with the installation 7 | 8 | > You now have SQL Server installed and running locally on your Windows computer! Check out the next section to continue installing prerequisites. 9 | -------------------------------------------------------------------------------- /_includes/partials/install_sql_server_windows_ML.md: -------------------------------------------------------------------------------- 1 | 1. If you don’t have SQL Server 2016 Developer (or above) installed: 2 | 3 | *Click [**here**](https://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2017-ctp/) to download the preview of SQL Server 2017 4 | 5 | *Click here [**here**](http://go.microsoft.com/fwlink/?LinkID=799009) to download the SQL Server 2016 exe (This version only supports R for Machine Learning) 6 | 7 | 2. Run it to start the SQL installer 8 | 3. Click *Accept*> after you have read the license terms 9 | 4. On the *Feature Selection* page, select: R Services (In-Database) for SQL Server 2016 or Machine Learning Services (In-Database) for SQL Server 2017 10 | 5. Don't forget to choose R/Python or both 11 | 6. If you chose R: On the page, *Consent to Install Microsoft R Open*>, click *Accept*. 12 | 7. If you chose Python: On the page, *Consent to Python*>, click *Accept*. 13 | 8. Click *Install* to proceed with the installation 14 | 15 | > You now have SQL Server installed with in-database ML services, running locally on your Windows computer! Check out the next section to continue installing prerequisites. 16 | -------------------------------------------------------------------------------- /_includes/partials/install_sqlcmd_linux_rhel.md: -------------------------------------------------------------------------------- 1 | SQLCMD is a command line tool that enables you to connect to SQL Server and run queries. 2 | 3 | ```terminal 4 | sudo su 5 | curl https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-tools.repo 6 | exit 7 | sudo ACCEPT_EULA=Y yum install msodbcsql mssql-tools 8 | sudo yum install unixODBC-devel 9 | echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile 10 | echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc 11 | source ~/.bashrc 12 | ``` 13 | 14 | Run a basic query. 15 | 16 | ```terminal 17 | sqlcmd -S localhost -U sa -P yourpassword -Q "SELECT @@VERSION" 18 | ``` 19 | 20 | ```results 21 | -------------------------------------------------------- 22 | Microsoft SQL Server vNext (CTP1.3) - 14.0.304.100 (X64) 23 | Feb 8 2017 04:21:38 24 | Copyright (c) Microsoft Corporation 25 | on Linux (Ubuntu 16.04) 26 | 27 | 1 rows(s) returned 28 | 29 | Executed in 1 ns 30 | ``` 31 | 32 | > You have successfully installed SQL Server Command Line Utilities on your RedHat machine! 33 | -------------------------------------------------------------------------------- /_includes/partials/install_sqlcmd_linux_sles.md: -------------------------------------------------------------------------------- 1 | SQLCMD is a command line tool that enables you to connect to SQL Server and run queries. 2 | 3 | ```terminal 4 | sudo su 5 | zypper ar https://packages.microsoft.com/config/sles/12/prod.repo 6 | zypper update 7 | exit 8 | sudo ACCEPT_EULA=Y zypper install msodbcsql mssql-tools 9 | sudo zypper install unixODBC-devel 10 | echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile 11 | echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc 12 | source ~/.bashrc 13 | ``` 14 | 15 | Run a basic query. 16 | 17 | ```terminal 18 | sqlcmd -S localhost -U sa -P yourpassword -Q "SELECT @@VERSION" 19 | ``` 20 | 21 | ```results 22 | -------------------------------------------------------- 23 | Microsoft SQL Server vNext (CTP1.3) - 14.0.304.100 (X64) 24 | Feb 8 2017 04:21:38 25 | Copyright (c) Microsoft Corporation 26 | on Linux (Ubuntu 16.04) 27 | 28 | 1 rows(s) returned 29 | 30 | Executed in 1 ns 31 | ``` 32 | 33 | > You have successfully installed SQL Server Command Line Utilities on your SLES machine! 34 | -------------------------------------------------------------------------------- /_includes/partials/install_sqlcmd_linux_ubuntu.md: -------------------------------------------------------------------------------- 1 | SQLCMD is a command line tool that enables you to connect to SQL Server and run queries. 2 | 3 | ```terminal 4 | sudo su 5 | curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-tools.list 6 | exit 7 | sudo apt-get update 8 | sudo ACCEPT_EULA=Y apt-get install mssql-tools 9 | sudo apt-get install unixodbc-dev 10 | echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile 11 | echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc 12 | source ~/.bashrc 13 | ``` 14 | 15 | Run a basic query. 16 | 17 | ```terminal 18 | sqlcmd -S localhost -U sa -P yourpassword -Q "SELECT @@VERSION" 19 | ``` 20 | 21 | ```results 22 | -------------------------------------------------------- 23 | Microsoft SQL Server vNext (CTP1.3) - 14.0.304.100 (X64) 24 | Feb 8 2017 04:21:38 25 | Copyright (c) Microsoft Corporation 26 | on Linux (Ubuntu 16.04) 27 | 28 | 1 rows(s) returned 29 | 30 | Executed in 1 ns 31 | ``` 32 | 33 | > You have successfully installed SQL Server Command Line Utilities on your Ubuntu 34 | -------------------------------------------------------------------------------- /_includes/partials/install_sqlcmd_mac.md: -------------------------------------------------------------------------------- 1 | SQLCMD is a command line tool that enables you to connect to SQL Server and run queries. 2 | 3 | ```terminal 4 | brew tap microsoft/mssql-preview https://github.com/Microsoft/homebrew-mssql-preview 5 | brew update 6 | ACCEPT_EULA=y brew install msodbcsql mssql-tools 7 | ``` 8 | Run a basic query. 9 | 10 | ```terminal 11 | sqlcmd -S localhost -U sa -P yourpassword -Q "SELECT @@VERSION" 12 | ``` 13 | 14 | ```results 15 | -------------------------------------------------------- 16 | Microsoft SQL Server vNext (CTP1.3) - 14.0.304.100 (X64) 17 | Feb 8 2017 04:21:38 18 | Copyright (c) Microsoft Corporation 19 | on Linux (Ubuntu 16.04) 20 | 21 | 1 rows(s) returned 22 | 23 | Executed in 1 ns 24 | ``` 25 | 26 | > You have successfully installed SQL Server Command Line Utilities on your macOS 27 | -------------------------------------------------------------------------------- /_includes/partials/install_sqlcmd_windows.md: -------------------------------------------------------------------------------- 1 | SQLCMD is a command line tool that enables you to connect to SQL Server and run queries. 2 | 3 | 1. Install the [**ODBC Driver**](https://www.microsoft.com/en-us/download/details.aspx?id=53339) 4 | 2. Install the [**SQL Server Command Line Utilities**](https://www.microsoft.com/en-us/download/details.aspx?id=53591) 5 | 6 | Once you install both the msi's, open up cmd.exe and run the following command to connect and run a basic query. 7 | 8 | ```terminal 9 | sqlcmd -S localhost -U sa -P yourpassword -Q "SELECT @@VERSION" 10 | ``` 11 | 12 | ```results 13 | -------------------------------------------------------- 14 | Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (X64) 15 | Apr 29 2016 23:23:58 16 | Copyright (c) Microsoft Corporation 17 | Developer Edition (64-bit) 18 | 19 | 1 rows(s) returned 20 | 21 | Executed in 1 ns. 22 | ``` 23 | > You have successfully installed SQL Server Command Line Utilities on your Windows machine! 24 | 25 | -------------------------------------------------------------------------------- /_includes/partials/step3/mssql.md: -------------------------------------------------------------------------------- 1 | Use the **mssql** extension for VS Code to connect to SQL Server running in Linux, Windows or Docker, Azure SQL DB and Azure SQL DW. ... See more Get rich T-SQL language services (ex. IntelliSense and keyword completion), while typing queries and run your queries to see results – all within VS Code and on Linux, Mac and Windows. 2 | 3 | Follow the steps [here](https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-develop-use-vscode) to install and use the **mssql** extension for VS Code. 4 | 5 | ![VSCode Extension]({{site.url}}/assets/images/VSCode_Extension.png) -------------------------------------------------------------------------------- /_includes/partials/step3/note.md: -------------------------------------------------------------------------------- 1 | Note! With the introduction of Service Pack 1 for SQL Server 2016, features in the database engine related to application development are now available across all editions of SQL Server (from Express through Enterprise). This includes innovations that can significantly improve your application’s throughput, latency, and security. Examples include the in-memory columnstore used in this tutorial, in-memory OLTP, data compression, table partitioning, Hadoop integration with PolyBase, Always Encrypted, row-level security, and data masking. Enjoy! -------------------------------------------------------------------------------- /_includes/partials/step3/title.md: -------------------------------------------------------------------------------- 1 | > Now that you have explored the basics, you are ready to see how you can make your app better with SQL Server. In this module we will show you a simple example of Columnstore Indexes and how they can improve data processing speeds. Columnstore Indexes can achieve up to 100x better performance on analytical workloads and up to 10x better data compression than traditional rowstore indexes. -------------------------------------------------------------------------------- /_includes/questions.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Have Questions? 4 |

5 |

6 | Happy to help! You can find us on GitHub, MSDN Forums, and StackOverflow. We also monitor the #SQLServerDev hashtag on Twitter. 7 |

8 |
-------------------------------------------------------------------------------- /_includes/resources.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | To get general documentations 5 |

6 | 9 | Read the SQL Server ML Services documentation 10 | 11 |
12 | 13 |
14 |

15 | Check out other related resources 16 |

17 | {% if site.resources %} 18 | 28 | {% endif %} 29 |
30 |
31 | -------------------------------------------------------------------------------- /_includes/scripts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /_layouts/default-menutop.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include head.html %} 5 | 6 | 7 | 8 | {% include header-menutop.html %} 9 | 10 |
11 |
12 | {{ content }} 13 |
14 |
15 | 16 | {% include footer.html %} 17 | {% include scripts.html %} 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include head.html %} 5 | 6 | 7 | 8 | {% include header.html %} 9 | 10 |
11 |
12 | {{ content }} 13 |
14 |
15 | 16 | {% include footer.html %} 17 | {% include scripts.html %} 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /_layouts/home.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {% include home.html %} 6 | -------------------------------------------------------------------------------- /_layouts/page-steps.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-menutop 3 | --- 4 |
5 | 6 | {% if site.steps %} 7 | {% assign separator = '/step/' %} 8 | {% assign baseLink = page.permalink | split: separator %} 9 | {% assign baseNumber = baseLink[1] | times: 1 %} 10 | 11 |

12 | {{page.title}} using {{page.language}} and SQL Server ML Services 13 |

14 | 15 |
16 | {% for step in site.steps %} 17 | {% assign number = step[0] %} 18 | {% assign value = step[1] | replace: '$$', page.language %} 19 | 20 |
21 | {%if number > 1 %} 22 | 25 | {{ number }} 26 | {{ value }} 27 | 28 | {% else %} 29 | 32 | {{ number }} 33 | {{ value }} 34 | 35 | {% endif %} 36 |
37 | {% endfor %} 38 |
39 | {% endif %} 40 | 41 |
42 |

43 |

44 |

45 |

46 |
47 |
48 |

49 |
50 |
51 |

52 |
53 |
54 |
55 |
56 |

57 |

58 |
59 |
60 |
61 |

62 |
63 |
64 |

65 |

66 |
67 |
68 | 69 |
70 | 71 | 74 | 75 | {% if site.steps %} 76 | {% assign stepsSize = site.steps | size %} 77 | {% if baseNumber < stepsSize %} 78 | {% assign nextNumber = baseNumber | plus: 1 %} 79 | 80 | {% if nextNumber == 1 %} 81 | {% assign nextNumber = nextNumber | plus: 1 %} 82 | {% endif %} 83 | 84 | 87 | Go to step {{nextNumber}} 88 | 89 | 90 | {% else %} 91 | 92 | {% if {{page.language}} == "Python" %} 93 | 94 | More SQL Server ML Tutorials 95 | 96 | {% elsif {{page.language}} == "R" %} 97 | 98 | More SQL Server ML Tutorials 99 | 100 | {% else %} 101 | 102 | cta6 103 | 104 | {% endif %} 105 | {% include resources.html %} 106 | {% endif %} 107 | {% endif %} 108 | 109 | {% include questions.html %} 110 | 111 | {% if site.disqus.shortname %} 112 | 115 | {% endif %} 116 |
117 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-menutop 3 | --- 4 |
5 | 6 |
7 |

{{ page.title | escape }}

8 |
9 |
10 | {{ content }} 11 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /_sass/base/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | @import 'mixins/fonts'; 3 | 4 | // Fonts 5 | @include font-include('Segoe UI', '//c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest', $font-weight-light, normal); 6 | @include font-include('Segoe UI', '//c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest', $font-weight-normal, normal); 7 | @include font-include('Segoe UI', '//c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest', $font-weight-bold, normal); 8 | -------------------------------------------------------------------------------- /_sass/base/_functions.scss: -------------------------------------------------------------------------------- 1 | @import 'functions/image'; -------------------------------------------------------------------------------- /_sass/base/_globals.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | html, 4 | body { 5 | $font-size: 16px; 6 | background: $color-background-brighter; 7 | font-family: 'Segoe UI'; 8 | font-size: $font-size; 9 | height: 100%; 10 | width: 100%; 11 | 12 | @media screen and (max-width: $media-screen-m) { 13 | font-size: $font-size * .8; 14 | } 15 | 16 | @media screen and (max-width: $media-screen-s) { 17 | font-size: $font-size * .65; 18 | } 19 | } 20 | 21 | strong { 22 | font-weight: $font-weight-bold; 23 | } -------------------------------------------------------------------------------- /_sass/base/_states.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | @import 'mixins/medias'; 3 | 4 | .is { 5 | &-hidden { 6 | display: none; 7 | } 8 | 9 | &-disabled { 10 | @include medias { 11 | opacity: .5; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /_sass/base/_utilities.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | .u { 4 | 5 | &-wrapper { 6 | $padding: $wrapper-default; 7 | padding-bottom: 0; 8 | padding-left: $padding; 9 | padding-right: $padding; 10 | padding-top: 0; 11 | width: 100%; 12 | 13 | @media screen and (max-width: $media-screen-s) { 14 | $padding: $wrapper-s; 15 | padding-left: $padding; 16 | padding-right: $padding; 17 | } 18 | } 19 | 20 | &-align { 21 | &-center { 22 | text-align: center; 23 | } 24 | 25 | &-left { 26 | text-align: left; 27 | } 28 | 29 | &-right { 30 | text-align: right; 31 | } 32 | } 33 | 34 | &-center { 35 | &-vertical { 36 | display: block; 37 | position: absolute; 38 | top: 50%; 39 | transform: translateY(-50%); 40 | } 41 | 42 | &-horizontal { 43 | display: block; 44 | left: 50%; 45 | position: absolute; 46 | transform: translateX(-50%); 47 | } 48 | 49 | &-both { 50 | display: block; 51 | left: 50%; 52 | position: absolute; 53 | top: 50%; 54 | transform: translate(-50%, -50%); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /_sass/base/_variables.scss: -------------------------------------------------------------------------------- 1 | // Colors 2 | $color-brand: #5C2D91; 3 | $color-brand-dark: darken($color-brand, 10%); 4 | $color-brand-darker: darken($color-brand, 20%); 5 | $color-brand-bright: lighten($color-brand, 10%); 6 | $color-brand-brighter: lighten($color-brand, 20%); 7 | $color-brand-brightest: lighten($color-brand, 50%); 8 | 9 | $color-secondary: #036CBF; 10 | $color-secondary-dark: darken($color-secondary, 10%); 11 | $color-secondary-darker: darken($color-secondary, 20%); 12 | $color-secondary-bright: lighten($color-secondary, 10%); 13 | $color-secondary-brighter: lighten($color-secondary, 20%); 14 | $color-secondary-brightest: lighten($color-secondary, 60%); 15 | 16 | $color-background-dark: #333333; 17 | $color-background-darker: #000000; 18 | $color-background-bright: #F2F2F2; 19 | $color-background-brighter: #FFF; 20 | 21 | $color-foreground-dark: #5B4C4C; 22 | $color-foreground-darker: #000000; 23 | $color-foreground-bright: #EEEEEE; 24 | $color-foreground-brighter: #FFFFFF; 25 | 26 | $color-star: #F5CB01; 27 | $color-next: #008400; 28 | 29 | // Animations 30 | $animation-speed-fast: .15s; 31 | $animation-speed-default: .35s; 32 | $animation-speed-slow: .5s; 33 | $animation-speed-slower: 2s; 34 | 35 | // Fonts 36 | $font-weight-light: 200; 37 | $font-weight-normal: 400; 38 | $font-weight-bold: 700; 39 | 40 | $font-size-xs: .4rem; // 6px 41 | $font-size-s: .85rem; // 13.6px 42 | $font-size-m: 1rem; // 16px 43 | $font-size-l: 1.125rem; // 18px 44 | $font-size-xl: 1.5rem; // 24px 45 | $font-size-xxl: 2.2rem; // 35px 46 | 47 | // Medias 48 | $media-screen-xxs: 360px; 49 | $media-screen-xs: 640px; 50 | $media-screen-s: 768px; 51 | $media-screen-m: 1024px; 52 | $media-screen-l: 1280px; 53 | $media-screen-xl: 1440px; 54 | $media-screen-xxl: 1680px; 55 | $media-screen-xxxl: 1920px; 56 | 57 | // Margins 58 | $margin-center: 10vw; 59 | $margin-logo: 8vw; 60 | 61 | // Wrapper 62 | $wrapper-default: 15vw; 63 | $wrapper-s: 5vw; 64 | 65 | // Borders 66 | $border-menu-color: rgba($color-background-darker, .1); 67 | $border-menu-size: 1px; 68 | $border-menu-radius: .3rem; 69 | 70 | // Shadows 71 | $shadow-default: 0 .1rem 0.6rem 0 rgba($color-background-darker, .1); 72 | 73 | // Variables for mixins 74 | $medias: xxs, xs, s, m, l, xl, xxl, xxxl; 75 | $mediavalues: $media-screen-xxs, $media-screen-xs, $media-screen-s, $media-screen-m, $media-screen-l, $media-screen-xl, $media-screen-xxl, $media-screen-xxxl; 76 | -------------------------------------------------------------------------------- /_sass/base/functions/_image.scss: -------------------------------------------------------------------------------- 1 | $path: 'images/'; 2 | 3 | @function image($name) { 4 | @return #{'url(' + $path + $name + ')'}; 5 | } -------------------------------------------------------------------------------- /_sass/base/mixins/_fonts.scss: -------------------------------------------------------------------------------- 1 | // @Author https://gist.github.com/jonathantneal/d0460e5c2d5d7f9bc5e6 2 | 3 | // ============================================================================= 4 | // String Replace 5 | // ============================================================================= 6 | 7 | @function str-replace($string, $search, $replace: '') { 8 | $index: str-index($string, $search); 9 | 10 | @if $index { 11 | @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); 12 | } 13 | 14 | @return $string; 15 | } 16 | 17 | // ============================================================================= 18 | // Font Face 19 | // ============================================================================= 20 | 21 | @mixin font-face($name, $url, $weight: null, $style: null, $exts: eot woff ttf svg) { 22 | $src: null; 23 | 24 | $extmods: ( eot: '?', svg: '#' + str-replace($name, ' ', '_') ); 25 | 26 | $formats: ( otf: 'opentype', ttf: 'truetype' ); 27 | 28 | @each $ext in $exts { 29 | $extmod: if(map-has-key($extmods, $ext), $ext + map-get($extmods, $ext), $ext); 30 | $format: if(map-has-key($formats, $ext), map-get($formats, $ext), $ext); 31 | $src: append($src, url(quote($url + '.' + $extmod)) format(quote($format)), comma); 32 | } 33 | 34 | @font-face { 35 | font-family: quote($name); 36 | font-style: $style; 37 | font-weight: $weight; 38 | src: $src; 39 | } 40 | 41 | 42 | } 43 | 44 | /*= require fonts */ 45 | 46 | @mixin font-include($font, $url, $weight: null, $style: null) { 47 | @include font-face($font, $url, $weight, $style); 48 | } 49 | -------------------------------------------------------------------------------- /_sass/base/mixins/_medias.scss: -------------------------------------------------------------------------------- 1 | @import '../variables'; 2 | 3 | @mixin medias { 4 | @content; 5 | 6 | @each $media in $medias { 7 | &\@#{$media} { 8 | @media screen and (max-width: nth($mediavalues, index($medias, $media))) { 9 | @content; 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /_sass/components/_disqus.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-disqus { 4 | margin-bottom: 3rem; 5 | } -------------------------------------------------------------------------------- /_sass/components/_footer.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-footer { 4 | $padding: 6vw; 5 | background-color: $color-background-dark; 6 | color: $color-foreground-brighter; 7 | display: flex; 8 | flex-wrap: wrap; 9 | justify-content: space-between; 10 | padding-bottom: $padding * .25; 11 | padding-left: $padding; 12 | padding-right: $padding; 13 | padding-top: $padding * .25; 14 | 15 | &-col { 16 | $padding: 1%; 17 | $width: 20%; 18 | 19 | align-content: flex-start; 20 | display: flex; 21 | flex-wrap: wrap; 22 | padding-left: $padding; 23 | padding-right: $padding; 24 | width: $width; 25 | 26 | &--double { 27 | width: $width * 1.8 - $padding * 2; 28 | } 29 | 30 | &--social { 31 | float: right !important; 32 | width: $width * 1.4 - $padding * 2; 33 | } 34 | } 35 | 36 | &-title { 37 | color: $color-foreground-brighter; 38 | padding-bottom: .5rem; 39 | width: 100%; 40 | } 41 | 42 | &-link { 43 | color: $color-foreground-brighter; 44 | font-weight: $font-weight-light; 45 | padding-top: 1rem; 46 | width: 100%; 47 | 48 | &--half { 49 | width: 50%; 50 | } 51 | 52 | &:hover { 53 | color: $color-secondary-bright; 54 | transition: color $animation-speed-default; 55 | } 56 | } 57 | 58 | &-icons { 59 | width: 100%; 60 | } 61 | 62 | &-icon { 63 | color: $color-foreground-brighter; 64 | float:right !important; 65 | font-size: 2.5rem !important; 66 | margin-right: .5rem; 67 | 68 | &:hover { 69 | color: $color-brand-brighter; 70 | transition: color $animation-speed-default; 71 | } 72 | } 73 | 74 | &-copy { 75 | font-size: 1rem; 76 | padding-top: 2.5rem; 77 | width: 100%; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /_sass/components/_header.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-header { 4 | $padding: 1rem; 5 | padding-top: $padding; 6 | 7 | &--empty { 8 | background: transparent; 9 | } 10 | 11 | &-content { 12 | text-align: center; 13 | } 14 | 15 | &-title { 16 | color: $color-secondary; 17 | display: block; 18 | font-size: $font-size-xxl; 19 | margin-bottom: 1.5rem; 20 | margin-top: 4rem; 21 | } 22 | 23 | &-subtitle { 24 | color: $color-foreground-darker; 25 | display: block; 26 | font-size: $font-size-xl; 27 | font-weight: $font-weight-light; 28 | margin-bottom: 3rem; 29 | margin-top: 1rem; 30 | } 31 | 32 | &-micro { 33 | left: $margin-logo; 34 | position: absolute; 35 | top: 1rem; 36 | width: 5rem; 37 | } 38 | } -------------------------------------------------------------------------------- /_sass/components/_home.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-home { 4 | $border: solid 1px rgba($color-background-darker, .1); 5 | $margin: 3%; 6 | 7 | padding-top: 3rem; 8 | 9 | &-title { 10 | font-weight: $font-weight-normal; 11 | padding-bottom: 2rem; 12 | text-align: center; 13 | width: 100%; 14 | } 15 | 16 | &-message { 17 | display: block; 18 | font-weight: $font-weight-normal; 19 | margin-top: 5rem; 20 | padding-bottom: 6rem; 21 | text-align: center; 22 | width: 100%; 23 | } 24 | 25 | &-items { 26 | align-items: center; 27 | display: flex; 28 | flex-wrap: wrap; 29 | justify-content: center; 30 | } 31 | 32 | &-item { 33 | align-items: center; 34 | background-color: $color-background-brighter; 35 | border: $border; 36 | border-radius: .3rem; 37 | box-shadow: $shadow-default; 38 | color: $color-foreground-dark; 39 | display: flex; 40 | font-size: $font-size-m; 41 | font-weight: $font-weight-light; 42 | justify-content: space-around; 43 | margin-left: $margin; 44 | margin-right: $margin; 45 | position: relative; 46 | width: 40% - 2 * $margin; 47 | 48 | &--column { 49 | flex-direction: column; 50 | height: 15rem; 51 | width: 40% - 2 * $margin; 52 | } 53 | 54 | .sql-new { 55 | margin-right: $margin; 56 | } 57 | } 58 | 59 | &-itemflex { 60 | display: flex; 61 | justify-content: center; 62 | width: 100%; 63 | } 64 | 65 | &-icon { 66 | background-color: $color-background-bright; 67 | display: inline-block; 68 | height: 3rem; 69 | 70 | &--block { 71 | background-color: transparent; 72 | display: block; 73 | height: auto; 74 | margin-bottom: 1rem; 75 | padding-top: .5rem; 76 | width: 9rem; 77 | } 78 | } 79 | 80 | &-link { 81 | color: $color-secondary-bright; 82 | text-align: center; 83 | 84 | &:hover { 85 | color: $color-secondary; 86 | transition: color $animation-speed-default; 87 | } 88 | 89 | &--underline { 90 | text-decoration: underline; 91 | 92 | &:hover { 93 | text-decoration: underline; 94 | } 95 | } 96 | 97 | &--spaced { 98 | $margin: 1rem; 99 | margin-left: $margin; 100 | margin-right: $margin; 101 | } 102 | } 103 | 104 | &-footer { 105 | $size: 14rem; 106 | $padding: 3.5rem; 107 | 108 | box-shadow: inset 0 $size 0 $color-background-bright; 109 | margin-top: 4rem; 110 | overflow: visible; 111 | padding-top: $padding; 112 | position: relative; 113 | z-index: 1; 114 | 115 | &:before { 116 | background-color: $color-background-bright; 117 | content: ''; 118 | height: $size; 119 | left: -$wrapper-default; 120 | position: absolute; 121 | top: 0; 122 | width: #{'calc(100% + ' + $wrapper-default * 2 + ')'}; 123 | z-index: -1; 124 | 125 | @media screen and (max-width: $media-screen-s) { 126 | left: -$wrapper-s; 127 | width: #{'calc(100% + ' + $wrapper-s * 2 + ')'}; 128 | } 129 | } 130 | } 131 | 132 | &-text { 133 | display: block; 134 | padding: 1rem; 135 | text-align: center; 136 | width: 100%; 137 | } 138 | } -------------------------------------------------------------------------------- /_sass/components/_main.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | @import '../base/functions'; 3 | 4 | .sql-main { 5 | background-image: image('bg.png'); 6 | background-size: contain; 7 | background-repeat: no-repeat; 8 | min-height: 50vh; 9 | 10 | &.is-default { 11 | background-image: none; 12 | } 13 | } -------------------------------------------------------------------------------- /_sass/components/_menu.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | @import '../base/functions'; 3 | 4 | .sql-menu { 5 | $width: 100%; 6 | $margin: .5%; 7 | $items: 6; 8 | $padding: 1.2rem; 9 | $border: solid $border-menu-size $border-menu-color; 10 | 11 | animation: show-item $animation-speed-slower forwards; 12 | background-image: image('hero-image.png'), image('hero-image_sub.png'); 13 | background-position: bottom center; 14 | background-repeat: no-repeat; 15 | background-size: cover; 16 | width: 100%; 17 | 18 | &-wrapper { 19 | align-items: center; 20 | display: flex; 21 | justify-content: center; 22 | max-width: 1920px; 23 | text-align: center; 24 | width: $width; 25 | } 26 | 27 | &-title { 28 | color: $color-foreground-bright; 29 | font-size: $font-size-l; 30 | font-weight: $font-weight-normal; 31 | margin-bottom: 2.5rem; 32 | padding-top: 2rem; 33 | } 34 | 35 | &-sub { 36 | animation: show-item $animation-speed-slow forwards; 37 | background-color: $color-background-bright; 38 | border: $border; 39 | border-radius: $border-menu-radius; 40 | box-shadow: $shadow-default; 41 | color: $color-foreground-dark; 42 | font-size: $font-size-m; 43 | font-weight: $font-weight-light; 44 | height: 15rem; 45 | margin-left: $margin; 46 | margin-right: $margin; 47 | opacity: 0; 48 | overflow: hidden; 49 | padding-bottom: $padding; 50 | padding-top: $padding; 51 | position: relative; 52 | width: $width / $items - 2 * $margin; 53 | 54 | @keyframes show-item { 55 | 0% { 56 | opacity: 0; 57 | } 58 | 59 | 100% { 60 | opacity: 1; 61 | } 62 | } 63 | 64 | @for $i from 0 through $items { 65 | &:nth-of-type(#{$i}) { 66 | animation-delay: $i * $animation-speed-slow * .25; 67 | } 68 | } 69 | } 70 | 71 | &-items { 72 | background-color: $color-background-brighter; 73 | display: none; 74 | height: 100%; 75 | width: 100%; 76 | } 77 | 78 | &-item { 79 | background-color: $color-background-brighter; 80 | border-top: $border; 81 | color: $color-secondary-bright; 82 | display: block; 83 | font-size: $font-size-s; 84 | padding-bottom: $padding / 2; 85 | padding-top: $padding / 2; 86 | position: relative; 87 | 88 | &:hover { 89 | background-color: $color-secondary-bright; 90 | color: $color-foreground-brighter; 91 | cursor: pointer; 92 | transition: all $animation-speed-default; 93 | 94 | .sql-new:before { 95 | background-color: $color-secondary-dark; 96 | transition: background-color $animation-speed-default; 97 | } 98 | } 99 | 100 | &:last-of-type { 101 | border-bottom: $border; 102 | } 103 | } 104 | 105 | &-logo { 106 | display: block; 107 | margin-bottom: 2rem; 108 | margin-left: auto; 109 | margin-right: auto; 110 | margin-top: 3rem; 111 | max-width: 60%; 112 | } 113 | 114 | &-sub:hover { 115 | padding-bottom: 0; 116 | padding-top: 0; 117 | transition: all $animation-speed-default; 118 | } 119 | 120 | &-sub:hover &-type { 121 | display: none; 122 | } 123 | 124 | &-sub:hover &-items { 125 | animation: menu-block-cursor $animation-speed-default * .8 forwards; // change time to have the click event just in time 126 | display: block; 127 | 128 | @keyframes menu-block-cursor { 129 | 0%, 130 | 99% { 131 | pointer-events: none; 132 | } 133 | 134 | 100% { 135 | pointer-events: auto; 136 | } 137 | } 138 | } 139 | 140 | &-sub:hover &-logo { 141 | margin-bottom: .25rem; 142 | margin-top: 1rem; 143 | max-width: 30%; 144 | transition: all $animation-speed-default; 145 | } 146 | } -------------------------------------------------------------------------------- /_sass/components/_menutop.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-menutop { 4 | $width: 40vw; 5 | $items: 6; 6 | $padding: 1.2rem; 7 | 8 | align-items: center; 9 | background-color: $color-brand; 10 | display: flex; 11 | justify-content: space-between; 12 | margin-top: 2rem; 13 | padding-left: $margin-logo; 14 | 15 | &-link { 16 | color: $color-foreground-brighter; 17 | text-transform: capitalize; 18 | } 19 | 20 | &-sub { 21 | border: solid $border-menu-size transparent; 22 | color: $color-foreground-brighter; 23 | font-weight: $font-weight-light; 24 | display: inline-block; 25 | padding-bottom: $padding; 26 | padding-top: $padding; 27 | position: relative; 28 | width: $width / $items; 29 | 30 | &.is-active { 31 | background-color: rgba($color-background-brighter, .1); 32 | font-weight: $font-weight-normal; 33 | } 34 | 35 | &:hover { 36 | background-color: $color-background-brighter; 37 | border-color: $border-menu-color; 38 | font-weight: $font-weight-normal; 39 | cursor: default; 40 | } 41 | } 42 | 43 | &-items { 44 | display: none; 45 | margin-left: -$border-menu-size; 46 | margin-top: $border-menu-size; 47 | position: absolute; 48 | top: 100%; 49 | width: 100%; 50 | z-index: 100; 51 | } 52 | 53 | &-item { 54 | background-color: $color-background-brighter; 55 | border: solid $border-menu-size $border-menu-color; 56 | border-top: 0; 57 | color: $color-secondary-bright; 58 | display: block; 59 | font-weight: $font-weight-light; 60 | padding-bottom: $padding / 2; 61 | padding-left: $padding / 2; 62 | padding-right: $padding / 2; 63 | padding-top: $padding / 2; 64 | position: relative; 65 | text-align: left; 66 | width: ($width / $items) * 2; 67 | 68 | &.is-active { 69 | background-color: $color-secondary-brightest; 70 | font-weight: $font-weight-normal; 71 | } 72 | 73 | &:hover { 74 | background-color: $color-secondary-bright; 75 | color: $color-foreground-brighter; 76 | cursor: pointer; 77 | transition: all $animation-speed-default; 78 | 79 | .sql-new:before { 80 | background-color: $color-secondary-dark; 81 | transition: background-color $animation-speed-default; 82 | } 83 | } 84 | 85 | &:last-of-type { 86 | border-bottom-left-radius: $border-menu-radius; 87 | border-bottom-right-radius: $border-menu-radius; 88 | } 89 | 90 | .sql-new { 91 | transform: translateY(-.3rem); 92 | } 93 | } 94 | 95 | &-sub:hover &-items { 96 | animation: menu-top-show $animation-speed-default forwards; 97 | display: block; 98 | 99 | @keyframes menu-top-show { 100 | 0% { 101 | opacity: 0; 102 | } 103 | 104 | 100% { 105 | opacity: 1; 106 | } 107 | } 108 | } 109 | 110 | &-sub:hover &-link { 111 | color: $color-brand; 112 | } 113 | 114 | &-sub:last-of-type &-item { 115 | margin-left: - $width / $items; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /_sass/components/_new.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-new { 4 | $size: 1.2rem; 5 | display: inline-block; 6 | height: 0; 7 | position: relative; 8 | transform: translateY(-.2rem); 9 | width: 0; 10 | 11 | &:before { 12 | background-color: $color-secondary-bright; 13 | border-radius: 50%; 14 | color: $color-foreground-brighter; 15 | content: 'new'; 16 | display: inline-block; 17 | font-size: $font-size-xs; 18 | height: $size; 19 | line-height: $size; 20 | text-align: center; 21 | text-transform: uppercase; 22 | width: $size; 23 | } 24 | } -------------------------------------------------------------------------------- /_sass/components/_page-steps.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-page_steps { 4 | $pages: Terminal, SQL, JavaScript, Results, Java, XML, Csharp, PHP, Python, Ruby, Javascript; 5 | $colors: #295651, #8A0F1B, #AB9807, #458B00, #C9720E, #1C66DD, #8000FF, #8DB6CD, #54D35D, #AA3333, #ab9807; 6 | 7 | &-hero { 8 | $padding: 2rem; 9 | color: $color-secondary; 10 | font-size: $font-size-xl; 11 | padding-bottom: $padding * 1.25; 12 | padding-top: $padding; 13 | text-align: center; 14 | } 15 | 16 | &-steps { 17 | align-items: center; 18 | display: flex; 19 | justify-content: center; 20 | margin-bottom: 3rem; 21 | 22 | &.is-sticky { 23 | $top: -5rem; 24 | 25 | animation: page-steps-sticky $animation-speed-default forwards; 26 | justify-content: center; 27 | left: 0; 28 | position: fixed; 29 | top: $top; 30 | width: 100%; 31 | z-index: 100; 32 | 33 | @keyframes page-steps-sticky { 34 | 0% { 35 | top: $top; 36 | } 37 | 38 | 90% { 39 | top: 0; 40 | } 41 | 42 | 100% { 43 | top: -.2rem; 44 | } 45 | } 46 | } 47 | } 48 | 49 | &-intro { 50 | font-size: $font-size-m; 51 | line-height: $font-size-m * 1.25; 52 | margin-bottom: 3rem; 53 | margin-top: 1rem; 54 | } 55 | 56 | $height: 4rem; 57 | $height-s: 2rem; 58 | &-step { 59 | $padding: 1.5rem; 60 | $margin: .5vw; 61 | 62 | align-items: center; 63 | background-color: $color-background-bright; 64 | border-radius: $height; 65 | color: $color-foreground-dark; 66 | display: flex; 67 | font-size: $font-size-m; 68 | height: $height; 69 | margin-left: $margin; 70 | margin-right: $margin; 71 | padding-bottom: $padding; 72 | padding-left: $padding / 2; 73 | padding-right: $padding / 2; 74 | padding-top: $padding; 75 | 76 | &:hover { 77 | background-color: $color-brand; 78 | transition: background-color $animation-speed-default; 79 | } 80 | } 81 | 82 | &-link { 83 | align-items: center; 84 | color: $color-brand; 85 | display: flex; 86 | height: $height; 87 | } 88 | 89 | &-number { 90 | $height: $height * .8; 91 | align-content: center; 92 | align-items: center; 93 | background-color: $color-background-brighter; 94 | border: 1px solid $color-brand; 95 | border-radius: 50%; 96 | color: $color-brand; 97 | display: inline-flex; 98 | font-size: $height * .6; 99 | height: $height; 100 | justify-content: center; 101 | margin-right: 1rem; 102 | width: $height; 103 | } 104 | 105 | &-link--active &-number { 106 | background-color: $color-brand; 107 | color: $color-foreground-brighter; 108 | } 109 | 110 | &-step:hover &-link { 111 | color: $color-foreground-brighter; 112 | transition: color $animation-speed-default; 113 | } 114 | 115 | &-step:hover &-number { 116 | background-color: $color-background-brighter; 117 | border-color: $color-background-brighter; 118 | color: $color-brand; 119 | transition: all $animation-speed-default; 120 | } 121 | 122 | &-steps.is-sticky &-step { 123 | $margin: .5vw; 124 | border: $border-menu-size solid rgba($color-brand, .2); 125 | border-radius: .5rem; 126 | border-top: 0; 127 | border-top-left-radius: 0; 128 | border-top-right-radius: 0; 129 | box-shadow: $shadow-default; 130 | height: $height-s; 131 | margin-left: $margin; 132 | margin-right: $margin; 133 | margin-top: 0; 134 | } 135 | 136 | &-steps.is-sticky &-number { 137 | $height: $height-s * .8; 138 | font-size: $height * .6; 139 | height: $height; 140 | width: $height; 141 | } 142 | 143 | $padding-block: 5vw; 144 | $padding-title: 1rem; 145 | &-block { 146 | background-color: $color-background-bright; 147 | box-shadow: inset 0 $padding-title * 3 0 $color-secondary; 148 | margin-bottom: 2.5rem; 149 | padding-bottom: $padding-block / 2; 150 | padding-left: $padding-block * 2; 151 | padding-right: $padding-block; 152 | } 153 | 154 | &-title { 155 | color: $color-foreground-brighter; 156 | font-size: $font-size-l; 157 | margin-bottom: 1.5rem; 158 | margin-left: - $padding-block * 2; 159 | margin-top: 1rem; 160 | padding-bottom: $padding-title; 161 | padding-left: $padding-title * 2; 162 | padding-top: $padding-title; 163 | } 164 | 165 | &-copy { 166 | $padding: .5rem; 167 | background-color: $color-background-dark; 168 | cursor: pointer; 169 | font-size: $font-size-s; 170 | margin-top: 0 !important; 171 | opacity: .8; 172 | padding-bottom: $padding / 2; 173 | padding-left: $padding; 174 | padding-right: $padding; 175 | padding-top: $padding / 2; 176 | position: absolute; 177 | right: 0; 178 | top: 0; 179 | transition: opacity $animation-speed-default; 180 | 181 | &:hover { 182 | opacity: 1; 183 | transition: opacity $animation-speed-default; 184 | } 185 | } 186 | 187 | &-star { 188 | color: $color-star; 189 | padding-right: .5em; 190 | } 191 | 192 | &-loading { 193 | margin: 2rem; 194 | padding-bottom: 100vh; 195 | width: 100%; 196 | 197 | // Fake loading data structure 198 | 199 | p, 200 | div { 201 | background-color: $color-background-bright; 202 | height: $font-size-m; 203 | margin-bottom: 1rem; 204 | padding: .5rem; 205 | width: 100%; 206 | } 207 | 208 | div { 209 | height: $font-size-m * 5; 210 | } 211 | } 212 | 213 | &-next { 214 | border-radius: .25rem; 215 | background-color: $color-next; 216 | color: $color-foreground-brighter; 217 | display: block; 218 | margin-bottom: 3rem; 219 | margin-left: auto; 220 | margin-right: auto; 221 | margin-top: 0; 222 | padding: 1rem; 223 | text-align: center; 224 | width: 15rem; 225 | 226 | &:hover { 227 | background-color: darken($color-next, 10%); 228 | transition: background-color $animation-speed-default; 229 | } 230 | } 231 | 232 | // Styles to improve markdown, not the best practise but necessary 233 | &-intro, 234 | &-block { 235 | a { 236 | border-bottom: 2px solid $color-secondary; 237 | color: $color-secondary; 238 | text-decoration: none; 239 | 240 | &:hover { 241 | border-color: $color-secondary-dark; 242 | color: $color-secondary-dark; 243 | transition: all $animation-speed-default; 244 | } 245 | } 246 | } 247 | 248 | &-block { 249 | font-size: $font-size-m; 250 | line-height: $font-size-m * 1.35; 251 | 252 | p, 253 | ol, 254 | div { 255 | margin-top: 1rem; 256 | margin-bottom: .5rem; 257 | } 258 | 259 | ol { 260 | list-style-position: inside; 261 | list-style-type: decimal; 262 | } 263 | 264 | li { 265 | margin-bottom: .75rem; 266 | 267 | p { 268 | display: inline-block; 269 | margin-top: 0; 270 | max-width: 90%; 271 | vertical-align: top; 272 | } 273 | } 274 | 275 | img { 276 | max-width: 100%; 277 | } 278 | 279 | .highlighter-rouge { 280 | position: relative; 281 | } 282 | 283 | .highlight { 284 | max-height: 80vh; 285 | min-height: 4rem; 286 | } 287 | 288 | pre[class*="language-"] { 289 | margin-top: 0 !important; 290 | } 291 | 292 | .prism-show-language { 293 | margin-top: 0; 294 | width: 0; 295 | 296 | &-label { 297 | margin-top: .3rem; 298 | top: 0 !important; 299 | 300 | @each $item in $pages { 301 | $i: index($pages, $item); 302 | &.#{$item} { 303 | background-color: nth($colors, $i); 304 | } 305 | } 306 | } 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /_sass/components/_questions.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-questions { 4 | margin-bottom: 1rem; 5 | 6 | &-title { 7 | font-weight: $font-weight-bold; 8 | margin-bottom: 1rem; 9 | } 10 | 11 | &-text { 12 | font-size: $font-size-m; 13 | line-height: $font-size-m * 1.25; 14 | width: 82%; 15 | 16 | a { 17 | border-bottom: 2px solid $color-secondary; 18 | color: $color-secondary; 19 | text-decoration: none; 20 | 21 | &:hover { 22 | border-color: $color-secondary-dark; 23 | color: $color-secondary-dark; 24 | transition: all $animation-speed-default; 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /_sass/components/_resources.scss: -------------------------------------------------------------------------------- 1 | @import '../base/variables'; 2 | 3 | .sql-resources { 4 | $padding: 5vw; 5 | 6 | border: $border-menu-size solid $border-menu-color; 7 | border-radius: $border-menu-radius; 8 | box-shadow: $shadow-default; 9 | margin-bottom: 3rem; 10 | padding-bottom: 2.5rem; 11 | padding-left: $padding; 12 | padding-right: $padding; 13 | padding-top: 2rem; 14 | 15 | &-header { 16 | align-items: center; 17 | border-bottom: $border-menu-size solid $color-foreground-dark; 18 | display: flex; 19 | justify-content: flex-start; 20 | padding-bottom: 2rem; 21 | } 22 | 23 | &-title { 24 | font-weight: $font-weight-bold; 25 | } 26 | 27 | &-button { 28 | background-color: $color-background-bright; 29 | border: $border-menu-size solid $border-menu-color; 30 | border-radius: $border-menu-radius; 31 | color: $color-secondary; 32 | margin-left: 1rem; 33 | padding: 1rem; 34 | 35 | &:hover { 36 | background-color: $color-secondary; 37 | color: $color-foreground-brighter; 38 | transition: all $animation-speed-default; 39 | } 40 | } 41 | 42 | &-list { 43 | padding-top: 2rem; 44 | } 45 | 46 | &-items { 47 | columns: 2; 48 | padding-left: 2.1rem; 49 | padding-top: 2rem; 50 | } 51 | 52 | &-item { 53 | font-size: $font-size-m; 54 | line-height: $font-size-m * 1.25; 55 | margin-bottom: .75rem; 56 | margin-right: 1.5rem; 57 | 58 | &:before { 59 | $size: .4rem; 60 | background-color: $color-background-darker; 61 | border-radius: 50%; 62 | content: ''; 63 | display: inline-block; 64 | height: $size; 65 | padding-right: .25rem; 66 | transform: translateY(-.1rem); 67 | width: $size; 68 | } 69 | } 70 | 71 | &-link { 72 | border-bottom: 2px solid $color-secondary; 73 | color: $color-secondary; 74 | text-decoration: none; 75 | 76 | &:hover { 77 | border-color: $color-secondary-dark; 78 | color: $color-secondary-dark; 79 | transition: all $animation-speed-default; 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /_sass/minima.scss: -------------------------------------------------------------------------------- 1 | // Base Helpers 2 | @import 3 | 'base/states', 4 | 'base/utilities', 5 | 'base/fonts' 6 | ; 7 | 8 | // Vendor 9 | @import 10 | 'vendor/normalize', 11 | 'vendor/reset', 12 | 'vendor/prism' 13 | ; 14 | 15 | // Base Files 16 | @import 17 | 'base/globals' 18 | ; 19 | 20 | // Components 21 | // Components structure (BEM no strict) 22 | // .ck- (the module) 23 | // .ck-component (the block) 24 | // .ck-component-child (the element) 25 | // DON'T DO THAT .ck-component-child-child2 - div.ck-component-child > div.ck-component-child-child2 26 | // BETTER THAT .ck-component-child .ck-component-child2 - div.ck-component-child > div.ck-component-child2 27 | // .ck-component--modifier (the modifier) 28 | @import 29 | 'components/main', 30 | 'components/header', 31 | 'components/footer', 32 | 'components/page-steps', 33 | 'components/menu', 34 | 'components/questions', 35 | 'components/menutop', 36 | 'components/new', 37 | 'components/home', 38 | 'components/resources', 39 | 'components/disqus' 40 | ; 41 | -------------------------------------------------------------------------------- /_sass/vendor/_normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v6.0.0 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in 9 | * IE on Windows Phone and in iOS. 10 | */ 11 | 12 | html { 13 | line-height: 1.15; /* 1 */ 14 | -ms-text-size-adjust: 100%; /* 2 */ 15 | -webkit-text-size-adjust: 100%; /* 2 */ 16 | } 17 | 18 | /* Sections 19 | ========================================================================== */ 20 | 21 | /** 22 | * Add the correct display in IE 9-. 23 | */ 24 | 25 | article, 26 | aside, 27 | footer, 28 | header, 29 | nav, 30 | section { 31 | display: block; 32 | } 33 | 34 | /** 35 | * Correct the font size and margin on `h1` elements within `section` and 36 | * `article` contexts in Chrome, Firefox, and Safari. 37 | */ 38 | 39 | h1 { 40 | font-size: 2em; 41 | margin: 0.67em 0; 42 | } 43 | 44 | /* Grouping content 45 | ========================================================================== */ 46 | 47 | /** 48 | * Add the correct display in IE 9-. 49 | * 1. Add the correct display in IE. 50 | */ 51 | 52 | figcaption, 53 | figure, 54 | main { /* 1 */ 55 | display: block; 56 | } 57 | 58 | /** 59 | * Add the correct margin in IE 8. 60 | */ 61 | 62 | figure { 63 | margin: 1em 40px; 64 | } 65 | 66 | /** 67 | * 1. Add the correct box sizing in Firefox. 68 | * 2. Show the overflow in Edge and IE. 69 | */ 70 | 71 | hr { 72 | box-sizing: content-box; /* 1 */ 73 | height: 0; /* 1 */ 74 | overflow: visible; /* 2 */ 75 | } 76 | 77 | /** 78 | * 1. Correct the inheritance and scaling of font size in all browsers. 79 | * 2. Correct the odd `em` font sizing in all browsers. 80 | */ 81 | 82 | pre { 83 | font-family: monospace, monospace; /* 1 */ 84 | font-size: 1em; /* 2 */ 85 | } 86 | 87 | /* Text-level semantics 88 | ========================================================================== */ 89 | 90 | /** 91 | * 1. Remove the gray background on active links in IE 10. 92 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 93 | */ 94 | 95 | a { 96 | background-color: transparent; /* 1 */ 97 | -webkit-text-decoration-skip: objects; /* 2 */ 98 | } 99 | 100 | /** 101 | * 1. Remove the bottom border in Chrome 57- and Firefox 39-. 102 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 103 | */ 104 | 105 | abbr[title] { 106 | border-bottom: none; /* 1 */ 107 | text-decoration: underline; /* 2 */ 108 | text-decoration: underline dotted; /* 2 */ 109 | } 110 | 111 | /** 112 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 113 | */ 114 | 115 | b, 116 | strong { 117 | font-weight: inherit; 118 | } 119 | 120 | /** 121 | * Add the correct font weight in Chrome, Edge, and Safari. 122 | */ 123 | 124 | b, 125 | strong { 126 | font-weight: bolder; 127 | } 128 | 129 | /** 130 | * 1. Correct the inheritance and scaling of font size in all browsers. 131 | * 2. Correct the odd `em` font sizing in all browsers. 132 | */ 133 | 134 | code, 135 | kbd, 136 | samp { 137 | font-family: monospace, monospace; /* 1 */ 138 | font-size: 1em; /* 2 */ 139 | } 140 | 141 | /** 142 | * Add the correct font style in Android 4.3-. 143 | */ 144 | 145 | dfn { 146 | font-style: italic; 147 | } 148 | 149 | /** 150 | * Add the correct background and color in IE 9-. 151 | */ 152 | 153 | mark { 154 | background-color: #ff0; 155 | color: #000; 156 | } 157 | 158 | /** 159 | * Add the correct font size in all browsers. 160 | */ 161 | 162 | small { 163 | font-size: 80%; 164 | } 165 | 166 | /** 167 | * Prevent `sub` and `sup` elements from affecting the line height in 168 | * all browsers. 169 | */ 170 | 171 | sub, 172 | sup { 173 | font-size: 75%; 174 | line-height: 0; 175 | position: relative; 176 | vertical-align: baseline; 177 | } 178 | 179 | sub { 180 | bottom: -0.25em; 181 | } 182 | 183 | sup { 184 | top: -0.5em; 185 | } 186 | 187 | /* Embedded content 188 | ========================================================================== */ 189 | 190 | /** 191 | * Add the correct display in IE 9-. 192 | */ 193 | 194 | audio, 195 | video { 196 | display: inline-block; 197 | } 198 | 199 | /** 200 | * Add the correct display in iOS 4-7. 201 | */ 202 | 203 | audio:not([controls]) { 204 | display: none; 205 | height: 0; 206 | } 207 | 208 | /** 209 | * Remove the border on images inside links in IE 10-. 210 | */ 211 | 212 | img { 213 | border-style: none; 214 | } 215 | 216 | /** 217 | * Hide the overflow in IE. 218 | */ 219 | 220 | svg:not(:root) { 221 | overflow: hidden; 222 | } 223 | 224 | /* Forms 225 | ========================================================================== */ 226 | 227 | /** 228 | * Remove the margin in Firefox and Safari. 229 | */ 230 | 231 | button, 232 | input, 233 | optgroup, 234 | select, 235 | textarea { 236 | margin: 0; 237 | } 238 | 239 | /** 240 | * Show the overflow in IE. 241 | * 1. Show the overflow in Edge. 242 | */ 243 | 244 | button, 245 | input { /* 1 */ 246 | overflow: visible; 247 | } 248 | 249 | /** 250 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 251 | * 1. Remove the inheritance of text transform in Firefox. 252 | */ 253 | 254 | button, 255 | select { /* 1 */ 256 | text-transform: none; 257 | } 258 | 259 | /** 260 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 261 | * controls in Android 4. 262 | * 2. Correct the inability to style clickable types in iOS and Safari. 263 | */ 264 | 265 | button, 266 | html [type="button"], /* 1 */ 267 | [type="reset"], 268 | [type="submit"] { 269 | -webkit-appearance: button; /* 2 */ 270 | } 271 | 272 | /** 273 | * Remove the inner border and padding in Firefox. 274 | */ 275 | 276 | button::-moz-focus-inner, 277 | [type="button"]::-moz-focus-inner, 278 | [type="reset"]::-moz-focus-inner, 279 | [type="submit"]::-moz-focus-inner { 280 | border-style: none; 281 | padding: 0; 282 | } 283 | 284 | /** 285 | * Restore the focus styles unset by the previous rule. 286 | */ 287 | 288 | button:-moz-focusring, 289 | [type="button"]:-moz-focusring, 290 | [type="reset"]:-moz-focusring, 291 | [type="submit"]:-moz-focusring { 292 | outline: 1px dotted ButtonText; 293 | } 294 | 295 | /** 296 | * 1. Correct the text wrapping in Edge and IE. 297 | * 2. Correct the color inheritance from `fieldset` elements in IE. 298 | * 3. Remove the padding so developers are not caught out when they zero out 299 | * `fieldset` elements in all browsers. 300 | */ 301 | 302 | legend { 303 | box-sizing: border-box; /* 1 */ 304 | color: inherit; /* 2 */ 305 | display: table; /* 1 */ 306 | max-width: 100%; /* 1 */ 307 | padding: 0; /* 3 */ 308 | white-space: normal; /* 1 */ 309 | } 310 | 311 | /** 312 | * 1. Add the correct display in IE 9-. 313 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 314 | */ 315 | 316 | progress { 317 | display: inline-block; /* 1 */ 318 | vertical-align: baseline; /* 2 */ 319 | } 320 | 321 | /** 322 | * Remove the default vertical scrollbar in IE. 323 | */ 324 | 325 | textarea { 326 | overflow: auto; 327 | } 328 | 329 | /** 330 | * 1. Add the correct box sizing in IE 10-. 331 | * 2. Remove the padding in IE 10-. 332 | */ 333 | 334 | [type="checkbox"], 335 | [type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Correct the cursor style of increment and decrement buttons in Chrome. 342 | */ 343 | 344 | [type="number"]::-webkit-inner-spin-button, 345 | [type="number"]::-webkit-outer-spin-button { 346 | height: auto; 347 | } 348 | 349 | /** 350 | * 1. Correct the odd appearance in Chrome and Safari. 351 | * 2. Correct the outline style in Safari. 352 | */ 353 | 354 | [type="search"] { 355 | -webkit-appearance: textfield; /* 1 */ 356 | outline-offset: -2px; /* 2 */ 357 | } 358 | 359 | /** 360 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 361 | */ 362 | 363 | [type="search"]::-webkit-search-cancel-button, 364 | [type="search"]::-webkit-search-decoration { 365 | -webkit-appearance: none; 366 | } 367 | 368 | /** 369 | * 1. Correct the inability to style clickable types in iOS and Safari. 370 | * 2. Change font properties to `inherit` in Safari. 371 | */ 372 | 373 | ::-webkit-file-upload-button { 374 | -webkit-appearance: button; /* 1 */ 375 | font: inherit; /* 2 */ 376 | } 377 | 378 | /* Interactive 379 | ========================================================================== */ 380 | 381 | /* 382 | * Add the correct display in IE 9-. 383 | * 1. Add the correct display in Edge, IE, and Firefox. 384 | */ 385 | 386 | details, /* 1 */ 387 | menu { 388 | display: block; 389 | } 390 | 391 | /* 392 | * Add the correct display in all browsers. 393 | */ 394 | 395 | summary { 396 | display: list-item; 397 | } 398 | 399 | /* Scripting 400 | ========================================================================== */ 401 | 402 | /** 403 | * Add the correct display in IE 9-. 404 | */ 405 | 406 | canvas { 407 | display: inline-block; 408 | } 409 | 410 | /** 411 | * Add the correct display in IE. 412 | */ 413 | 414 | template { 415 | display: none; 416 | } 417 | 418 | /* Hidden 419 | ========================================================================== */ 420 | 421 | /** 422 | * Add the correct display in IE 10-. 423 | */ 424 | 425 | [hidden] { 426 | display: none; 427 | } -------------------------------------------------------------------------------- /_sass/vendor/_prism.scss: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript+abap+actionscript+ada+apacheconf+apl+applescript+asciidoc+aspnet+autoit+autohotkey+bash+basic+batch+c+brainfuck+bro+bison+csharp+cpp+coffeescript+ruby+css-extras+d+dart+diff+docker+eiffel+elixir+erlang+fsharp+fortran+gherkin+git+glsl+go+graphql+groovy+haml+handlebars+haskell+haxe+http+icon+inform7+ini+j+jade+java+json+julia+keyman+kotlin+latex+less+livescript+lolcode+lua+makefile+markdown+matlab+mel+mizar+monkey+nasm+nginx+nim+nix+nsis+objectivec+ocaml+oz+parigp+parser+pascal+perl+php+php-extras+powershell+processing+prolog+properties+protobuf+puppet+pure+python+q+qore+r+jsx+rest+rip+roboconf+crystal+rust+sas+sass+scss+scala+scheme+smalltalk+smarty+sql+stylus+swift+tcl+textile+twig+typescript+verilog+vhdl+vim+wiki+xojo+yaml&plugins=show-language+previewer-base+previewer-color+previewer-easing+previewer-angle+command-line+normalize-whitespace */ 2 | /** 3 | * okaidia theme for JavaScript, CSS and HTML 4 | * Loosely based on Monokai textmate theme by http://www.monokai.nl/ 5 | * @author ocodia 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: #f8f8f2; 11 | background: none; 12 | text-shadow: 0 1px rgba(0, 0, 0, 0.3); 13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | /* Code blocks */ 32 | pre[class*="language-"] { 33 | padding: 1em; 34 | margin: .5em 0; 35 | overflow: auto; 36 | border-radius: 0.3em; 37 | } 38 | 39 | :not(pre) > code[class*="language-"], 40 | pre[class*="language-"] { 41 | background: #272822; 42 | } 43 | 44 | /* Inline code */ 45 | :not(pre) > code[class*="language-"] { 46 | padding: .1em; 47 | border-radius: .3em; 48 | white-space: normal; 49 | } 50 | 51 | .token.comment, 52 | .token.prolog, 53 | .token.doctype, 54 | .token.cdata { 55 | color: slategray; 56 | } 57 | 58 | .token.punctuation { 59 | color: #f8f8f2; 60 | } 61 | 62 | .namespace { 63 | opacity: .7; 64 | } 65 | 66 | .token.property, 67 | .token.tag, 68 | .token.constant, 69 | .token.symbol, 70 | .token.deleted { 71 | color: #f92672; 72 | } 73 | 74 | .token.boolean, 75 | .token.number { 76 | color: #ae81ff; 77 | } 78 | 79 | .token.selector, 80 | .token.attr-name, 81 | .token.string, 82 | .token.char, 83 | .token.builtin, 84 | .token.inserted { 85 | color: #a6e22e; 86 | } 87 | 88 | .token.operator, 89 | .token.entity, 90 | .token.url, 91 | .language-css .token.string, 92 | .style .token.string, 93 | .token.variable { 94 | color: #f8f8f2; 95 | } 96 | 97 | .token.atrule, 98 | .token.attr-value, 99 | .token.function { 100 | color: #e6db74; 101 | } 102 | 103 | .token.keyword { 104 | color: #66d9ef; 105 | } 106 | 107 | .token.regex, 108 | .token.important { 109 | color: #fd971f; 110 | } 111 | 112 | .token.important, 113 | .token.bold { 114 | font-weight: bold; 115 | } 116 | .token.italic { 117 | font-style: italic; 118 | } 119 | 120 | .token.entity { 121 | cursor: help; 122 | } 123 | 124 | div.prism-show-language { 125 | position: relative; 126 | } 127 | 128 | div.prism-show-language > div.prism-show-language-label { 129 | color: white; 130 | background-color: #CFCFCF; 131 | display: inline-block; 132 | position: absolute; 133 | bottom: auto; 134 | left: auto; 135 | top: 10px; 136 | right: 0; 137 | width: auto; 138 | height: auto; 139 | font-size: 1.0em; 140 | border-radius: 0 0 0 5px; 141 | padding: 0.25em 1.0em; 142 | text-shadow: none; 143 | z-index: 1; 144 | box-shadow: none; 145 | -webkit-transform: none; 146 | -moz-transform: none; 147 | -ms-transform: none; 148 | -o-transform: none; 149 | transform: none; 150 | opacity: 0.8; 151 | } 152 | 153 | .prism-previewer, 154 | .prism-previewer:before, 155 | .prism-previewer:after { 156 | position: absolute; 157 | pointer-events: none; 158 | } 159 | .prism-previewer, 160 | .prism-previewer:after { 161 | left: 50%; 162 | } 163 | .prism-previewer { 164 | margin-top: -48px; 165 | width: 32px; 166 | height: 32px; 167 | margin-left: -16px; 168 | 169 | opacity: 0; 170 | -webkit-transition: opacity .25s; 171 | -o-transition: opacity .25s; 172 | transition: opacity .25s; 173 | } 174 | .prism-previewer.flipped { 175 | margin-top: 0; 176 | margin-bottom: -48px; 177 | } 178 | .prism-previewer:before, 179 | .prism-previewer:after { 180 | content: ''; 181 | position: absolute; 182 | pointer-events: none; 183 | } 184 | .prism-previewer:before { 185 | top: -5px; 186 | right: -5px; 187 | left: -5px; 188 | bottom: -5px; 189 | border-radius: 10px; 190 | border: 5px solid #fff; 191 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75); 192 | } 193 | 194 | .prism-previewer:after { 195 | top: 100%; 196 | width: 0; 197 | height: 0; 198 | margin: 5px 0 0 -7px; 199 | border: 7px solid transparent; 200 | border-color: rgba(255, 0, 0, 0); 201 | border-top-color: #fff; 202 | } 203 | .prism-previewer.flipped:after { 204 | top: auto; 205 | bottom: 100%; 206 | margin-top: 0; 207 | margin-bottom: 5px; 208 | border-top-color: rgba(255, 0, 0, 0); 209 | border-bottom-color: #fff; 210 | } 211 | .prism-previewer.active { 212 | opacity: 1; 213 | } 214 | .prism-previewer-color { 215 | background-image: linear-gradient(45deg, #bbb 25%, transparent 25%, transparent 75%, #bbb 75%, #bbb), linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb); 216 | background-size: 10px 10px; 217 | background-position: 0 0, 5px 5px; 218 | } 219 | .prism-previewer-color:before { 220 | background-color: inherit; 221 | background-clip: padding-box; 222 | } 223 | 224 | .prism-previewer-easing { 225 | margin-top: -76px; 226 | margin-left: -30px; 227 | width: 60px; 228 | height: 60px; 229 | background: #333; 230 | } 231 | .prism-previewer-easing.flipped { 232 | margin-bottom: -116px; 233 | } 234 | .prism-previewer-easing svg { 235 | width: 60px; 236 | height: 60px; 237 | } 238 | .prism-previewer-easing circle { 239 | fill: hsl(200, 10%, 20%); 240 | stroke: white; 241 | } 242 | .prism-previewer-easing path { 243 | fill: none; 244 | stroke: white; 245 | stroke-linecap: round; 246 | stroke-width: 4; 247 | } 248 | .prism-previewer-easing line { 249 | stroke: white; 250 | stroke-opacity: 0.5; 251 | stroke-width: 2; 252 | } 253 | .prism-previewer-angle:before { 254 | border-radius: 50%; 255 | background: #fff; 256 | } 257 | .prism-previewer-angle:after { 258 | margin-top: 4px; 259 | } 260 | .prism-previewer-angle svg { 261 | width: 32px; 262 | height: 32px; 263 | -webkit-transform: rotate(-90deg); 264 | -moz-transform: rotate(-90deg); 265 | -ms-transform: rotate(-90deg); 266 | -o-transform: rotate(-90deg); 267 | transform: rotate(-90deg); 268 | } 269 | .prism-previewer-angle[data-negative] svg { 270 | -webkit-transform: scaleX(-1) rotate(-90deg); 271 | -moz-transform: scaleX(-1) rotate(-90deg); 272 | -ms-transform: scaleX(-1) rotate(-90deg); 273 | -o-transform: scaleX(-1) rotate(-90deg); 274 | transform: scaleX(-1) rotate(-90deg); 275 | } 276 | .prism-previewer-angle circle { 277 | fill: transparent; 278 | stroke: hsl(200, 10%, 20%); 279 | stroke-opacity: 0.9; 280 | stroke-width: 32; 281 | stroke-dasharray: 0, 500; 282 | } 283 | .command-line-prompt { 284 | border-right: 1px solid #999; 285 | display: block; 286 | float: left; 287 | font-size: 100%; 288 | letter-spacing: -1px; 289 | margin-right: 1em; 290 | pointer-events: none; 291 | 292 | -webkit-user-select: none; 293 | -moz-user-select: none; 294 | -ms-user-select: none; 295 | user-select: none; 296 | } 297 | 298 | .command-line-prompt > span:before { 299 | color: #999; 300 | content: ' '; 301 | display: block; 302 | padding-right: 0.8em; 303 | } 304 | 305 | .command-line-prompt > span[data-user]:before { 306 | content: "[" attr(data-user) "@" attr(data-host) "] $"; 307 | } 308 | 309 | .command-line-prompt > span[data-user="root"]:before { 310 | content: "[" attr(data-user) "@" attr(data-host) "] #"; 311 | } 312 | 313 | .command-line-prompt > span[data-prompt]:before { 314 | content: attr(data-prompt); 315 | } -------------------------------------------------------------------------------- /_sass/vendor/_reset.scss: -------------------------------------------------------------------------------- 1 | *, 2 | *::before, 3 | *::after { 4 | box-sizing: border-box; 5 | } 6 | 7 | a, 8 | a:active, 9 | a:hover, 10 | a:visited { 11 | text-decoration: none; 12 | } 13 | 14 | /* http://meyerweb.com/eric/tools/css/reset/ 15 | v2.0 | 20110126 16 | License: none (public domain) 17 | */ 18 | 19 | html, body, div, span, applet, object, iframe, 20 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 21 | a, abbr, acronym, address, big, cite, code, 22 | del, dfn, em, img, ins, kbd, q, s, samp, 23 | small, strike, strong, sub, sup, tt, var, 24 | b, u, i, center, 25 | dl, dt, dd, ol, ul, li, 26 | fieldset, form, label, legend, 27 | table, caption, tbody, tfoot, thead, tr, th, td, 28 | article, aside, canvas, details, embed, 29 | figure, figcaption, footer, header, hgroup, 30 | menu, nav, output, ruby, section, summary, 31 | time, mark, audio, video { 32 | margin: 0; 33 | padding: 0; 34 | border: 0; 35 | font-size: 100%; 36 | font: inherit; 37 | vertical-align: baseline; 38 | } 39 | /* HTML5 display-role reset for older browsers */ 40 | article, aside, details, figcaption, figure, 41 | footer, header, hgroup, menu, nav, section { 42 | display: block; 43 | } 44 | body { 45 | line-height: 1; 46 | } 47 | ol, ul { 48 | list-style: none; 49 | } 50 | blockquote, q { 51 | quotes: none; 52 | } 53 | blockquote:before, blockquote:after, 54 | q:before, q:after { 55 | content: ''; 56 | content: none; 57 | } 58 | table { 59 | border-collapse: collapse; 60 | border-spacing: 0; 61 | } -------------------------------------------------------------------------------- /application/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/application/__init__.pyc -------------------------------------------------------------------------------- /application/views.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/application/views.pyc -------------------------------------------------------------------------------- /assets/images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/Thumbs.db -------------------------------------------------------------------------------- /assets/images/VSCode_Extension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/VSCode_Extension.png -------------------------------------------------------------------------------- /assets/images/award.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/award.png -------------------------------------------------------------------------------- /assets/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/bg.png -------------------------------------------------------------------------------- /assets/images/channel9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/channel9.png -------------------------------------------------------------------------------- /assets/images/hero-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/hero-image.png -------------------------------------------------------------------------------- /assets/images/hero-image_sub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/hero-image_sub.png -------------------------------------------------------------------------------- /assets/images/menu/csharp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/menu/csharp.png -------------------------------------------------------------------------------- /assets/images/menu/java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/menu/java.png -------------------------------------------------------------------------------- /assets/images/menu/node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/menu/node.png -------------------------------------------------------------------------------- /assets/images/menu/php.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/menu/php.png -------------------------------------------------------------------------------- /assets/images/menu/python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/menu/python.png -------------------------------------------------------------------------------- /assets/images/menu/r-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/menu/r-logo.png -------------------------------------------------------------------------------- /assets/images/micro-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/micro-logo.png -------------------------------------------------------------------------------- /assets/images/newsletter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/newsletter.png -------------------------------------------------------------------------------- /assets/images/r-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sql-ml-tutorials/8149d62b36371ad4809c408b20757bb5ba4dd35d/assets/images/r-logo.png -------------------------------------------------------------------------------- /assets/scripts/steps.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | // Declare options 3 | var COPY_TIME = 2000; 4 | 5 | var selectors = { 6 | container: '.js-steps', 7 | header: '.js-stepsheader', 8 | copy: '.js-copy', 9 | loading: '.js-loading', 10 | quote: 'blockquote p', 11 | step: 'h2', 12 | }; 13 | 14 | var classes = { 15 | title: 'sql-page_steps-title', 16 | block: 'sql-page_steps-block', 17 | hidden: 'is-hidden', 18 | copy: 'js-copy sql-page_steps-copy', 19 | intro: 'sql-page_steps-intro', 20 | sticky: 'is-sticky' 21 | }; 22 | 23 | var texts = { 24 | copy: ' Copy', 25 | copied: 'Copied!', 26 | star: '' 27 | }; 28 | 29 | // Methods that we need 30 | var initContainer = function () { 31 | var $container = $(selectors.container); 32 | if ($container.length < 1) { 33 | return; 34 | } 35 | var $steps = $container.children(selectors.step); 36 | var $intro = $container.children(selectors.intro).first().addClass(classes.intro); 37 | var $newContainer = $('
'); 38 | $newContainer.html($intro); 39 | 40 | $steps.each(function (i, el) { 41 | var $el = $(el); 42 | $el.addClass(classes.title); 43 | var $step = $('
'); 44 | $step.addClass(classes.block); 45 | $step.append($el.nextUntil(selectors.step)); 46 | $step.find(selectors.quote).prepend(texts.star); 47 | $step.prepend($el); 48 | $newContainer.append($step); 49 | }); 50 | 51 | $container.append($newContainer); 52 | 53 | return $container; 54 | }; 55 | 56 | var initSticky = function () { 57 | var $window = $(window); 58 | var $header = $(selectors.header); 59 | if ($header.length < 1) { 60 | return; 61 | } 62 | var position = $header.position(); 63 | $window.on('scroll', function () { 64 | var top = $(window).scrollTop(); 65 | if (top > position.top) { 66 | $header.addClass(classes.sticky); 67 | return; 68 | } 69 | 70 | $header.removeClass(classes.sticky); 71 | }); 72 | }; 73 | 74 | var initCopy = function () { 75 | var options = { 76 | target: function (trigger) { 77 | return trigger.previousElementSibling; 78 | } 79 | }; 80 | 81 | var copy = new Clipboard(selectors.copy, options); 82 | 83 | copy.on('success', function (e) { 84 | e.clearSelection(); 85 | $el = $(e.trigger); 86 | $el.html(texts.copied); 87 | setTimeout(function () { 88 | $el.html(texts.copy); 89 | }, COPY_TIME); 90 | }); 91 | }; 92 | 93 | var generateCopyButton = function () { 94 | var $btn = $('
'); 95 | $btn.html(texts.copy); 96 | $btn.addClass(classes.copy); 97 | return $btn; 98 | }; 99 | /* 100 | $(document).ready(function() { 101 | 102 | console.log(window.location.href); 103 | console.log("test"); 104 | var path = window.location.href; 105 | var windows = "windows"; 106 | var isWindows; 107 | isWindows = path.includes(windows); 108 | }); 109 | 110 | */ 111 | var checkContent = function ($container) { 112 | // Terminal 113 | 114 | console.log(window.location.href); 115 | console.log("test"); 116 | var path = window.location.href; 117 | var windows = "windows"; 118 | var isWindows; 119 | isWindows = path.indexOf(windows); 120 | if (isWindows >=0){ 121 | $container 122 | .find('.language-terminal.highlighter-rouge pre') 123 | .addClass('command-line') 124 | .attr('data-prompt', '>'); 125 | } 126 | else{ 127 | $container 128 | .find('.language-terminal.highlighter-rouge pre') 129 | .addClass('command-line') 130 | .attr('data-prompt', '$'); 131 | } 132 | // Clipboard 133 | $container 134 | .find('.highlighter-rouge pre') 135 | .append(generateCopyButton()); 136 | 137 | return $container; 138 | }; 139 | 140 | 141 | // Init Sticky 142 | initSticky(); 143 | 144 | // Init the info of the container 145 | var $container = initContainer(); 146 | 147 | if ($container) { 148 | var $loading = $(selectors.loading); 149 | 150 | // Check for modifications 151 | $container = checkContent($container); 152 | 153 | // Initialize copy button 154 | initCopy(); 155 | 156 | // Show the content 157 | var TIME = 250; 158 | $loading.fadeOut(TIME); 159 | setTimeout(function() { 160 | $container.fadeIn(TIME * .5); 161 | }, TIME * .9); 162 | } 163 | })(jQuery); 164 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | --- 4 | -------------------------------------------------------------------------------- /pages/R/customerclustering/step-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: R 4 | title: Perform customer clustering 5 | permalink: /R/customerclustering/ 6 | redirect_from: 7 | - /R/ 8 | - /R/customerclustering/step/ 9 | - /R/customerclustering/step/1 10 | --- 11 | 12 | 13 | > In this tutorial, we are going to get ourselves familiar with clustering. **Clustering** can be explained as organizing data into groups where members of a group are similar in some way. 14 | We will be using the **Kmeans** algorithm to perform the clustering of customers. This can for example be used to target a specific group of customers for marketing efforts. 15 | Kmeans clustering is an unsupervised learning algorithm that tries to group data based on similarities. Unsupervised learning means that there is no outcome to be predicted, and the algorithm just tries to find patterns in the data. 16 | You will learn how to perform clustering using Kmeans and analyze the results. We will also cover how you can deploy a clustering solution using SQL Server. 17 | You can copy code as you follow the tutorial. All code is also available on [GitHub](https://github.com/Microsoft/sql-server-samples/tree/master/samples/features/r-services/getting-started/customer-clustering). 18 | 19 | 20 | ## Step 1.1 Install SQL Server with in-database R / Machine Learning Services 21 | {% include partials/install_sql_server_windows_ML.md %} 22 | 23 | ## Step 1.2 Install SQL Server Management Studio (SSMS) 24 | Download and install SQL Server Management studio: [SSMS](https://msdn.microsoft.com/en-us/library/mt238290.aspx) 25 | 26 | >Now you have installed a tool you can use to easily manage your database objects and scripts. 27 | 28 | 29 | ## Step 1.3 Enable external script execution 30 | Run SSMS and open a new query window. Then execute the script below to enable your instance to run R scripts in SQL Server. 31 | 32 | ```sql 33 | EXEC sp_configure 'external scripts enabled', 1; 34 | RECONFIGURE WITH OVERRIDE 35 | ``` 36 | You can read more about configuring Machine Learning Services [here](https://docs.microsoft.com/en-us/sql/advanced-analytics/r-services/set-up-sql-server-r-services-in-database). 37 | **Don't forget to restart your SQL Server Instance after the configuration!** You can restart in SSMS by right clicking on the instance name in the Object Explorer and choose *Restart*. 38 | 39 | Optional: If you want, you can also [download SSMS custom reports](https://github.com/Microsoft/sql-server-samples/blob/master/samples/features/r-services/ssms-custom-reports/R%20Services%20-%20Configuration.rdl) available on github. 40 | The report "R Services - Configuration.rdl" for example provides an overview of the R runtime parameters and gives you an option to configure your instance with a button click. 41 | To import a report in SSMS, right click on Server Objects in the SSMS Object Explorer and choose Reports -> Custom reports. Upload the .rdl file. 42 | 43 | >Now you have enabled external script execution so that you can run R code inside SQL Server! 44 | 45 | ## Install and configure your R development environment 46 | 1. You need to install an R IDE. Here are some suggestions: 47 | 48 | *R Tools for Visual Studio (RTVS) [Download](https://www.visualstudio.com/vs/rtvs) 49 | 50 | *RStudio [Download](https://www.rstudio.com) 51 | 52 | 2. To be able to use some of the functions in this tutorial, you need to configure your R IDE to point to Microsoft R Client, which is an R Runtime provided by Microsoft. This runtime contains MS R Open packages. 53 | Follow the steps 1 and 2 [here](https://msdn.microsoft.com/en-us/microsoft-r/r-client-get-started#configure-ide) to install R client and configure your R IDE tool. 54 | 55 | > Terrific, now your SQL Server instance is able to host and run R code and you have the necessary development tools installed and configured! The next section will walk you through how to do clustering using R. 56 | 57 | -------------------------------------------------------------------------------- /pages/R/customerclustering/step-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: R 4 | title: Perform customer clustering 5 | permalink: /R/customerclustering/step/2 6 | --- 7 | 8 | 9 | >After getting SQL Server with Machine Learning Services installed and your R IDE configured on your machine, you can now proceed and perform clustering using R. 10 | 11 | >R is a programming language that makes statistical and math computation easy, and is very useful for any machine learning/predictive analytics/statistics work. There are lots of tutorials out there on R. This is one example of a [tutorial](https://www.tutorialspoint.com/r/) to learn more about R. 12 | 13 | >In this specific scenario, we have an online store and we want to group customers based on their order and return behaviour. 14 | This information will help us target marketing efforts towards certain groups of customers. Before we go into how you can use R to perform this type of customer grouping using clustering in SQL Server 2016, we will look at the scenario in R. 15 | 16 | 17 | ## Step 2.1 Load the sample data 18 | 19 | **Restore the sample DB** 20 | The dataset used in this tutorial is hosted in several SQL Server tables.The tables contain purchasing and return data based on orders. 21 | 22 | 1. Download the backup (.bak) file [here](https://sqlchoice.blob.core.windows.net/sqlchoice/static/tpcxbb_1gb.bak), and save it on a location that SQL Server can access. 23 | For example in the folder where SQL Server is installed. 24 | Sample path: C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup 25 | 26 | 27 | 2. Once you have the file saved, open SSMS and a new query window to run the following commands to restore the DB. 28 | Make sure to modify the file paths and server name in the script. 29 | 30 | ```sql 31 | USE master; 32 | GO 33 | RESTORE DATABASE tpcxbb_1gb 34 | FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\tpcxbb_1gb.bak' 35 | WITH 36 | MOVE 'tpcxbb_1gb' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\tpcxbb_1gb.mdf' 37 | ,MOVE 'tpcxbb_1gb_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\tpcxbb_1gb.ldf'; 38 | GO 39 | ``` 40 | 41 | You should now be able to see the database and tables store_sales and store_returns in the Object Explorer in SSMS. 42 | You can also verify this by querying the tables in SSMS. Open a new query window and select the following. 43 | 44 | ```sql 45 | USE tpcxbb_1gb; 46 | SELECT TOP (100) * FROM [dbo].[store_sales]; 47 | SELECT TOP (100) * FROM [dbo].[store_returns]; 48 | ``` 49 | 50 | >You now have the database and the data to perform clustering. 51 | 52 | 53 | ## Step 2.2 Access the data from SQL Server using R 54 | 55 | Loading data from SQL Server to R is easy. So let's try it out. 56 | 57 | Open a new RScript in your R development tool and run the following script. 58 | Just don't forget to replace "MYSQLSERVER" with the name of your database instance. 59 | 60 | In the query we are using to select data from SQL Server, we are separating customers along the following dimensions: 61 | - *return frequency* 62 | - *return order ratio (total number of orders partially or fully returned versus the total number of orders)* 63 | - *return item ratio (total number of items returned versus the number of items purchased)* 64 | - *return amount ration (total monetary amount of items returned versus the amount purchased)* 65 | 66 | ```r 67 | #Connection string to connect to SQL Server. Don't forget to replace MyServer with the name of your SQL Server instance 68 | connStr <- paste("Driver=SQL Server;Server=", " MyServer", ";Database=" , "tpcxbb_1gb" , ";Trusted_Connection=true;" , sep="" ); 69 | 70 | #The query that we are using to select data from SQL Server 71 | input_query <- " 72 | SELECT 73 | ss_customer_sk AS customer, 74 | round(CASE WHEN ((orders_count = 0) OR (returns_count IS NULL) OR (orders_count IS NULL) OR ((returns_count / orders_count) IS NULL) ) THEN 0.0 ELSE (cast(returns_count as nchar(10)) / orders_count) END, 7) AS orderRatio, 75 | round(CASE WHEN ((orders_items = 0) OR(returns_items IS NULL) OR (orders_items IS NULL) OR ((returns_items / orders_items) IS NULL) ) THEN 0.0 ELSE (cast(returns_items as nchar(10)) / orders_items) END, 7) AS itemsRatio, 76 | round(CASE WHEN ((orders_money = 0) OR (returns_money IS NULL) OR (orders_money IS NULL) OR ((returns_money / orders_money) IS NULL) ) THEN 0.0 ELSE (cast(returns_money as nchar(10)) / orders_money) END, 7) AS monetaryRatio, 77 | round(CASE WHEN ( returns_count IS NULL ) THEN 0.0 ELSE returns_count END, 0) AS frequency 78 | --cast(round(cast(CASE WHEN (returns_count IS NULL) THEN 0.0 ELSE returns_count END as double)) as integer) AS frequency 79 | FROM 80 | ( 81 | SELECT 82 | ss_customer_sk, 83 | -- return order ratio 84 | COUNT(distinct(ss_ticket_number)) AS orders_count, 85 | -- return ss_item_sk ratio 86 | COUNT(ss_item_sk) AS orders_items, 87 | -- return monetary amount ratio 88 | SUM( ss_net_paid ) AS orders_money 89 | FROM store_sales s 90 | GROUP BY ss_customer_sk 91 | ) orders 92 | LEFT OUTER JOIN 93 | ( 94 | SELECT 95 | sr_customer_sk, 96 | -- return order ratio 97 | count(distinct(sr_ticket_number)) as returns_count, 98 | -- return ss_item_sk ratio 99 | COUNT(sr_item_sk) as returns_items, 100 | -- return monetary amount ratio 101 | SUM( sr_return_amt ) AS returns_money 102 | FROM store_returns 103 | GROUP BY sr_customer_sk 104 | ) returned ON ss_customer_sk=sr_customer_sk 105 | " 106 | ``` 107 | 108 | Results from the query are returned to R using the rxSqlServerData function. 109 | This is also where we define the type for columns we want to select (using colClasses), to make sure that the types are correctly transferred to R. 110 | 111 | ```r 112 | #Querying SQL Server using the query above and and getting the results back to data frame customer_returns 113 | #This is also where we define the type for columns we want to select (using colClasses), to make sure that the types are correctly transferred to R 114 | customer_returns <- RxSqlServerData(sqlQuery=input_query,colClasses=c(customer ="numeric" , orderRatio="numeric" , itemsRatio="numeric" , monetaryRatio="numeric" , frequency="numeric" ),connectionString=connStr); 115 | 116 | # Transform the data from an input dataset to an output dataset 117 | customer_data <- rxDataStep(customer_returns); 118 | 119 | #Look at the data we just loaded from SQL Server 120 | head(customer_data, n = 5); 121 | ``` 122 | ```results 123 | customer orderRatio itemsRatio monetaryRatio frequency 124 | 1 75675 0 0 0.071633 4 125 | 2 86750 0 0 0.000000 0 126 | 3 75343 0 0 0.000000 0 127 | 4 49280 0 0 0.000000 0 128 | 5 89406 0 0 0.000000 0 129 | 6 72426 0 0 0.000000 0 130 | ``` 131 | 132 | >You have now read the data from SQL Server to R and explored it. 133 | 134 | ## Step 2.3 Determine number of clusters 135 | 136 | Using the clustering algorithm **Kmeans**, is one of the simplest and most well known ways of grouping data. 137 | Now that we have our selected data, we can group the data into clusters using the iterative data mining algorithm called Kmeans. 138 | 139 | The algorithm accepts two inputs: The data itself, and a predefined number "k", the number of clusters. 140 | The output is k clusters with input data partitioned among them. 141 | 142 | The goal of K-means is to group the items into k clusters such that all items in same cluster are as similar to each other as possible. And items not in same cluster are as different as possible. 143 | It uses the distance measures to calculate similarity and dissimilarity. 144 | 145 | This is how the algorithm works: 146 | 147 | 1. It randomly chooses k points and make them the initial centroids (each cluster has a centroid which basically is the "center" of the cluster) 148 | 2. For each point, it finds the nearest centroid and assigns the point to the cluster associated with the nearest centroid 149 | 3. Updates the centroid of each cluster based on members in that cluster. Typically, a new centroid will be the average of all members in the cluster 150 | 4. Repeats steps 2 and 3, until the clusters are stable 151 | 152 | The number of clusters has to be predefined and the quality of the clusters is heavily dependent on the correctness of the k value specified. 153 | You could just randomly pick a number of clusters, run Kmeans and iterate your way to a good number. 154 | Or we can use R to evaluate which number of clusters is best for our dataset. Let's determine the number of clusters using R! 155 | ```r 156 | #Determine number of clusters 157 | #Using a plot of the within groups sum of squares, by number of clusters extracted, can help determine the appropriate number of clusters 158 | #We are looking for a bend in the plot. It is at this "elbow" in the plot that we have the appropriate number of clusters 159 | wss <- (nrow(customer_data) - 1) * sum(apply(customer_data, 2, var)) 160 | for (i in 2:20) 161 | wss[i] <- sum(kmeans(customer_data, centers = i)$withinss) 162 | plot(1:20, wss, type = "b", xlab = "Number of Clusters", ylab = "Within groups sum of squares") 163 | ``` 164 | 165 | ![Elbow graph](https://sqlchoice.blob.core.windows.net/sqlchoice/static/images/Elbow_graph.JPG) 166 | Finding the right number of clusters using an elbow graph 167 | 168 | Based on the graph above, it looks like *k = 4* would be a good value to try. That will group our customers into 4 clusters. 169 | 170 | >Now we have derived the number of clusters to use when clustering. 171 | 172 | 173 | ## Step 2.4 Perform Clustering 174 | Now it is time to use Kmeans. In this sample, we will be using the function rxKmeans which is the Kmeans function in the RevoScaleR package. 175 | 176 | ```r 177 | # Output table to hold the customer group mappings. This is a table where the cluster mappings will be saved in the database. 178 | # This table is generated from R 179 | return_cluster = RxSqlServerData(table = "return_cluster", connectionString = connStr); 180 | # Set.seed for random number generator for predictability 181 | set.seed(10); 182 | # Generate clusters using rxKmeans and output key / cluster to a table in SQL Server called return_cluster 183 | clust <- rxKmeans( ~ orderRatio + itemsRatio + monetaryRatio + frequency, customer_returns, numClusters=4 184 | , outFile=return_cluster, outColName="cluster" , extraVarsToWrite=c("customer"), overwrite=TRUE); 185 | 186 | # Read the customer returns cluster table from the DB 187 | customer_cluster <- rxDataStep(return_cluster); 188 | 189 | ``` 190 | 191 | >Great, now you have performed clustering in R! 192 | 193 | ## Step 2.5 Analyze results - Plot clusters 194 | 195 | R is very useful since it's easy to plot and visualize data for analysis. Now that we have done the clustering using Kmeans, we need to analyze it and see if we can learn anything from it. Sometimes plotting the clusters might be helpful, so let's do that. 196 | 197 | ```r 198 | #Plot the clusters (you need to install R library "cluster". If you don't have that installed, just uncomment the next line of code) 199 | #install.packages("cluster") 200 | library("cluster"); 201 | clusplot(customer_data, customer_cluster$cluster, color=TRUE, shade=TRUE, labels=4, lines=0, plotchar = TRUE); 202 | ``` 203 | ![Plot of the clusters](https://sqlchoice.blob.core.windows.net/sqlchoice/static/images/Cluster_plot.JPG) 204 | 205 | Unfortunaltely, this plot does not really tell us anything about how the different clusters are different from each other. 206 | We had 4 different variables and we need to know something about the different characteristics of each cluster to make conclusions. 207 | 208 | Using Kmeans is just a data mining method and you still need to spend time on analyzing the results. 209 | Depending on your data, you might need to use different methods to analyze the result. Here we just want to show that plotting can be one way. 210 | Let's try something else and see if we can get some more insight from that. 211 | 212 | >Now you have explored plotting as a method to evaluate the clusters. 213 | 214 | 215 | ## Step 2.6 Analyze cluster means 216 | 217 | The clust object contains the results from our Kmeans clustering. We are going to look at some mean values. 218 | 219 | ```r 220 | #Look at the clustering details and analyze results 221 | clust 222 | ``` 223 | 224 | ```results 225 | Call: 226 | rxKmeans(formula = ~orderRatio + itemsRatio + monetaryRatio + 227 | frequency, data = customer_returns, outFile = return_cluster, 228 | outColName = "cluster", extraVarsToWrite = c("customer"), 229 | overwrite = TRUE, numClusters = 4) 230 | Data: customer_returns 231 | Number of valid observations: 37336 232 | Number of missing observations: 0 233 | Clustering algorithm: 234 | 235 | K-means clustering with 4 clusters of sizes 31675, 671, 2851, 2139 236 | Cluster means: 237 | orderRatio itemsRatio monetaryRatio frequency 238 | 1 0.000000000 0.0000000000 0.00000000 0.000000 239 | 2 0.007451565 0.0000000000 0.04449653 4.271237 240 | 3 1.008067345 0.2707821817 0.49515232 1.031568 241 | 4 0.000000000 0.0004675082 0.10858272 1.186068 242 | Within cluster sum of squares by cluster: 243 | 1 2 3 4 244 | 0.0000 1329.0160 18561.3157 363.2188 245 | 246 | ``` 247 | 248 | Focusing on the cluster mean values, it seems like we can actually interpret something. 249 | Just to refresh our memory, here are the definitions of our variables: 250 | 251 | * *frequency = return frequency* 252 | * *orderRatio = return order ratio (total number of orders partially or fully returned versus the total number of orders)* 253 | * *itemsRatio = return item ratio (total number of items returned versus the number of items purchased)* 254 | * *monetaryRatio = return amount ratio (total monetary amount of items returned versus the amount purchased)* 255 | 256 | Some examples of what the mean values tell us? 257 | 258 | * Well, cluster 1 (the largest cluster) seems to be a group of customers that are not active. All values are zero. 259 | *And cluster 3 seems to be a group that stands out in terms of return behaviour. 260 | 261 | Data mining using Kmeans often requires further analysis of the results, and further steps to better understand each cluster, 262 | but it provides some very good leads. Cluster 1 is a set of customers who are clearly not active. Perhaps we can target marketing efforts towards this group to trigger an interest for purchases? 263 | Let's query the database for their email addresses so that we can send a marketing email to them. 264 | 265 | Use the following select statement to use the cluster data to select email addresses to customers in a specific cluster from te tables in SQL Server. 266 | 267 | Open a new query in SSMS and run the following select statement: 268 | 269 | ```sql 270 | USE [tpcxbb_1gb] 271 | SELECT customer.[c_email_address], customer.c_customer_sk 272 | FROM dbo.customer 273 | JOIN 274 | [dbo].[return_cluster] as r 275 | ON r.customer = customer.c_customer_sk 276 | WHERE r.cluster = 3 277 | ``` 278 | 279 | > Congrats you just performed clustering with R! Let us now deploy our R code by moving it to SQL Server. 280 | -------------------------------------------------------------------------------- /pages/R/customerclustering/step-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: R 4 | title: Perform customer clustering 5 | permalink: /R/customerclustering/step/3 6 | --- 7 | 8 | 9 | >In this section, we will move the R code we just wrote into SQL Server and deploy our clustering with the help of SQL Server Machine Learning Services. 10 | 11 | >In order to perform clustering on a regular basis, as new customers are registering, we need to be able call our R script from any App. 12 | To do that, we can simply delploy the R Script in SQL Server. You basically put the R script inside a SQL stored procedure in the database. A stored procedure is like a function, that takes parameters and can return results, and the good thing with these procedures is that they can be called from any application. 13 | 14 | 15 | ## Step 3.1 Create a stored procedure for clustering 16 | 17 | In SSMS, launch a new query window and run the following T-SQL script to create the stored procedure: 18 | 19 | ```sql 20 | USE [tpcxbb_1gb] 21 | DROP PROC IF EXISTS generate_customer_return_clusters; 22 | GO 23 | CREATE procedure [dbo].[generate_customer_return_clusters] 24 | AS 25 | /* 26 | This procedure uses R to classify customers into different groups based on their 27 | purchase & return history. 28 | */ 29 | BEGIN 30 | DECLARE @duration FLOAT 31 | , @instance_name NVARCHAR(100) = @@SERVERNAME 32 | , @database_name NVARCHAR(128) = db_name() 33 | -- Input query to generate the purchase history & return metrics 34 | , @input_query NVARCHAR(MAX) = N' 35 | SELECT 36 | ss_customer_sk AS customer, 37 | round(CASE WHEN ((orders_count = 0) OR (returns_count IS NULL) OR (orders_count IS NULL) OR ((returns_count / orders_count) IS NULL) ) THEN 0.0 ELSE (cast(returns_count as nchar(10)) / orders_count) END, 7) AS orderRatio, 38 | round(CASE WHEN ((orders_items = 0) OR(returns_items IS NULL) OR (orders_items IS NULL) OR ((returns_items / orders_items) IS NULL) ) THEN 0.0 ELSE (cast(returns_items as nchar(10)) / orders_items) END, 7) AS itemsRatio, 39 | round(CASE WHEN ((orders_money = 0) OR (returns_money IS NULL) OR (orders_money IS NULL) OR ((returns_money / orders_money) IS NULL) ) THEN 0.0 ELSE (cast(returns_money as nchar(10)) / orders_money) END, 7) AS monetaryRatio, 40 | round(CASE WHEN ( returns_count IS NULL ) THEN 0.0 ELSE returns_count END, 0) AS frequency 41 | 42 | FROM 43 | ( 44 | SELECT 45 | ss_customer_sk, 46 | -- return order ratio 47 | COUNT(distinct(ss_ticket_number)) AS orders_count, 48 | -- return ss_item_sk ratio 49 | COUNT(ss_item_sk) AS orders_items, 50 | -- return monetary amount ratio 51 | SUM( ss_net_paid ) AS orders_money 52 | FROM store_sales s 53 | GROUP BY ss_customer_sk 54 | ) orders 55 | LEFT OUTER JOIN 56 | ( 57 | SELECT 58 | sr_customer_sk, 59 | -- return order ratio 60 | count(distinct(sr_ticket_number)) as returns_count, 61 | -- return ss_item_sk ratio 62 | COUNT(sr_item_sk) as returns_items, 63 | -- return monetary amount ratio 64 | SUM( sr_return_amt ) AS returns_money 65 | FROM store_returns 66 | GROUP BY sr_customer_sk 67 | ) returned ON ss_customer_sk=sr_customer_sk 68 | ' 69 | EXEC sp_execute_external_script 70 | @language = N'R' 71 | , @script = N' 72 | # Define the connection string 73 | connStr <- paste("Driver=SQL Server;Server=", instance_name, " ;Database=", database_name, " ;Trusted_Connection=true;", sep="" ); 74 | 75 | # Input customer data that needs to be classified. This is the result we get from our query 76 | customer_returns <- RxSqlServerData(sqlQuery = input_query, 77 | colClasses = c(customer = "numeric", orderRatio = "numeric", itemsRatio = "numeric", monetaryRatio = "numeric", frequency = "numeric"), 78 | connectionString = connStr); 79 | 80 | # Output table to hold the customer cluster mappings 81 | return_cluster = RxSqlServerData(table = "customer_return_clusters", connectionString = connStr); 82 | 83 | # set.seed for random number generator for predicatability 84 | set.seed(10); 85 | 86 | # generate clusters using rxKmeans and output clusters to a table called "customer_return_clusters". 87 | clust <- rxKmeans( ~ orderRatio + itemsRatio + monetaryRatio + frequency, customer_returns, numClusters = 4 88 | , outFile = return_cluster, outColName = "cluster", writeModelVars = TRUE , extraVarsToWrite = c("customer"), overwrite = TRUE); 89 | ' 90 | , @input_data_1 = N'' 91 | , @params = N'@instance_name nvarchar(100), @database_name nvarchar(128), @input_query nvarchar(max), @duration float OUTPUT' 92 | , @instance_name = @instance_name 93 | , @database_name = @database_name 94 | , @input_query = @input_query 95 | , @duration = @duration OUTPUT; 96 | END; 97 | 98 | GO 99 | ``` 100 | 101 | >You have now created a stored procedure that contains the R script for clustering. 102 | 103 | 104 | ## Step 3.2 Perform clustering in SQL Server 105 | 106 | We are now going to execute the stored procedure in SQL Server to perform the clustering 107 | 108 | ```sql 109 | --Empty table of the results before running the stored procedure 110 | TRUNCATE TABLE customer_return_clusters; 111 | --Execute the clustering. This will load the table customer_return_clusters with cluster mappings 112 | EXEC [dbo].[generate_customer_return_clusters]; 113 | 114 | ``` 115 | 116 | Now let's verify that it works and that we actually have the list of customers and their cluster mappings 117 | 118 | ```sql 119 | --Now select data from table customer_return_clusters to verify that the clustering data was loaded 120 | SELECT * FROM customer_return_clusters; 121 | 122 | ``` 123 | 124 | >Congrats, you have performed clustering with R inside SQL Server! 125 | 126 | 127 | ## Step 3.3 Why is it useful to deploy this in SQL Server? 128 | 129 | We now have the clustering implemented in SQL Server. Why is that useful? 130 | 131 | Well, imagine that you need to perform clustering on you cutomer data on a regular basis as new customers sign up to keep an updated understanding of customer behavior. In this example, we might want to send out promotion emails and can select the email addresses of customers in cluster 3 to send out a promotion. 132 | 133 | You can also schedule jobs that run the stored procedure and automatically send the results to for example a CRM application or a reporting tool. 134 | 135 | The code below is selecting the email addresses of customers in cluster 3, for a promotion campaign: 136 | 137 | ```sql 138 | USE [tpcxbb_1gb] 139 | SELECT customer.[c_email_address], customer.c_customer_sk 140 | FROM dbo.customer 141 | JOIN 142 | [dbo].[customer_return_clusters] as r 143 | ON r.customer = customer.c_customer_sk 144 | WHERE r.cluster = 3 145 | ``` 146 | 147 | > Congrats, you have now performed clustering in SQL Server with R using SQL Server Machine Learning Services! 148 | -------------------------------------------------------------------------------- /pages/R/rentalprediction/step-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: R 4 | title: Build a predictive model 5 | permalink: /R/rentalprediction/ 6 | redirect_from: 7 | - /R/ 8 | - /R/rentalprediction/step/ 9 | - /R/rentalprediction/step/1 10 | --- 11 | 12 | 13 | Predictive modeling is a powerful way to add intelligence to your application. It enables applications to predict outcomes against new data. The act of incorporating predictive analytics into your applications involves two major phases: **model training** and **model deployment** 14 | 15 | In this tutorial, you will learn how to create a predictive model in R and deploy it with SQL Server 2016 (and above) Machine Learning Services. 16 | 17 | Here is a [video](https://www.youtube.com/watch?v=YCyj9cdi4Nk&feature=youtu.be) that introduces in-database analytics and predictive modeling with R in SQL Server. 18 | 19 | You can copy code as you follow this tutorial. All code is also available on [GitHub](https://github.com/NelGson/sql-server-samples/tree/master/samples/features/r-services/getting-started/rental-prediction) 20 | 21 | ## Step 1.1 Install SQL Server with in-database R / Machine Learning Services 22 | {% include partials/install_sql_server_windows_ML.md %} 23 | 24 | ## Step 1.2 Install SQL Server Management Studio (SSMS) 25 | Download and install SQL Server Management studio: [SSMS](https://msdn.microsoft.com/en-us/library/mt238290.aspx) 26 | 27 | >Now you have installed a tool you can use to easily manage your database objects and scripts. 28 | 29 | ## Step 1.3 Enable external script execution 30 | Run SSMS and open a new query window. Then execute the script below to enable your instance to run R scripts in SQL Server. 31 | 32 | ```sql 33 | EXEC sp_configure 'external scripts enabled', 1; 34 | RECONFIGURE WITH OVERRIDE 35 | ``` 36 | You can read more about configuring Machine Learning Services [here](https://docs.microsoft.com/en-us/sql/advanced-analytics/r-services/set-up-sql-server-r-services-in-database). 37 | **Don't forget to restart your SQL Server Instance after the configuration!** You can restart in SSMS by right clicking on the instance name in the Object Explorer and choose *Restart*. 38 | 39 | Optional: If you want, you can also [download SSMS custom reports](https://github.com/Microsoft/sql-server-samples/blob/master/samples/features/r-services/ssms-custom-reports/R%20Services%20-%20Configuration.rdl) available on github. 40 | The report "R Services - Configuration.rdl" for example provides an overview of the R runtime parameters and gives you an option to configure your instance with a button click. 41 | To import a report in SSMS, right click on Server Objects in the SSMS Object Explorer and choose Reports -> Custom reports. Upload the .rdl file. 42 | 43 | >Now you have enabled external script execution so that you can run R code inside SQL Server! 44 | 45 | ## Step 1.4 Install and configure your R development environment 46 | 1. You need to install an R IDE. Here are some suggestions: 47 | 48 | *R Tools for Visual Studio (RTVS) [Download](https://www.visualstudio.com/vs/rtvs) 49 | 50 | *RStudio [Download](https://www.rstudio.com) 51 | 52 | 2. To be able to use some of the functions in this tutorial, you need to configure your R IDE to point to Microsoft R Client, which is an R Runtime provided by Microsoft. This runtime contains MS R Open packages. 53 | 54 | Follow the steps 1 and 2 [here](https://msdn.microsoft.com/en-us/microsoft-r/r-client-get-started#configure-ide) to install R client and configure your R IDE tool. 55 | 56 | >Terrific, now your SQL Server instance is able to host and run R code and you have the necessary development tools installed and configured! 57 | The next section will walk you through creating a predictive model using R. 58 | 59 | -------------------------------------------------------------------------------- /pages/R/rentalprediction/step-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: R 4 | title: Build a predictive model 5 | permalink: /R/rentalprediction/step/2 6 | --- 7 | 8 | >After getting SQL Server with ML Services installed and your R IDE configured on your machine, you can now proceed to **train** a predictive model with R. 9 | >R is a programming language that makes statistical and math computation easy, and is very useful for any machine learning/predictive analytics/statistics work. 10 | There are lots of tutorials out there on R. This is one example of a [tutorial](https://www.tutorialspoint.com/r/) to learn more about R. 11 | 12 | >In this specific scenario, we own a ski rental business, and we want to predict the number of rentals that 13 | we will have on a future date. This information will help us to get ready from a stock, staff and facilities perspective. 14 | 15 | 16 | >During **model training**, you create and train a predictive model by showing it sample data along with the outcomes. Then you save this model so that you can use it later when you want to make predictions against new data. 17 | 18 | ## Step 2.1 Restore the sample DB 19 | 20 | 21 | The dataset used in this tutorial is hosted in a SQL Server table.The table contains rental data from previous years. 22 | 1.Download the backup (.bak) file [here](https://sqlchoice.blob.core.windows.net/sqlchoice/static/TutorialDB.bak), and save it on a location that SQL Server can access. 23 | For example in the folder where SQL Server is installed. 24 | Sample path: C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup 25 | 26 | 27 | 2.Once you have the file saved, open SSMS and a new query window to run the following commands to restore the DB. 28 | Make sure to modify the file paths and server name in the script. 29 | 30 | ```sql 31 | USE master; 32 | GO 33 | RESTORE DATABASE TutorialDB 34 | FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\TutorialDB.bak' 35 | WITH 36 | MOVE 'TutorialDB' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\TutorialDB.mdf' 37 | ,MOVE 'TutorialDB_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\TutorialDB.ldf'; 38 | GO 39 | ``` 40 | 41 | 42 | A table named rental_data containing the dataset should exist in the restored SQL Server database. 43 | You can verify this by querying the table in SSMS. 44 | 45 | 46 | ```sql 47 | USE tutorialdb; 48 | SELECT * FROM [dbo].[rental_data]; 49 | ``` 50 | 51 | >You now have the database and the data to use for training the model. 52 | 53 | ## Step 2.2 Access the data from SQL Server using R 54 | 55 | Loading data from SQL Server to R is easy. So let's try it out. 56 | Open a new RScript in your R development tool and run the following script. 57 | Just don't forget to replace "MYSQLSERVER" with the name of your database instance. 58 | 59 | ```r 60 | #Connection string to connect to SQL Server named instance 61 | connStr <- paste("Driver=SQL Server; Server=", "MYSQLSERVER", 62 | ";Database=", "Tutorialdb", ";Trusted_Connection=true;", sep = ""); 63 | 64 | #Get the data from SQL Server Table 65 | SQL_rentaldata <- RxSqlServerData(table = "dbo.rental_data", 66 | connectionString = connStr, returnDataFrame = TRUE); 67 | 68 | #Import the data into a data frame 69 | rentaldata <- rxImport(SQL_rentaldata); 70 | 71 | #Let's see the structure of the data and the top rows 72 | # Ski rental data, giving the number of ski rentals on a given date 73 | head(rentaldata); 74 | str(rentaldata); 75 | ``` 76 | 77 | ```results 78 | Year Month Day RentalCount WeekDay Holiday Snow 79 | 1 2014 1 20 445 2 1 0 80 | 2 2014 2 13 40 5 0 0 81 | 3 2013 3 10 456 1 0 0 82 | 4 2014 3 31 38 2 0 0 83 | 5 2014 4 24 23 5 0 0 84 | 6 2015 2 11 42 4 0 0 85 | 'data.frame': 453 obs. of 7 variables: 86 | $ Year : int 2014 2014 2013 2014 2014 2015 2013 2014 2013 2015 ... 87 | $ Month : num 1 2 3 3 4 2 4 3 4 3 ... 88 | $ Day : num 20 13 10 31 24 11 28 8 5 29 ... 89 | $ RentalCount: num 445 40 456 38 23 42 310 240 22 360 ... 90 | $ WeekDay : num 2 5 1 2 5 4 1 7 6 1 ... 91 | $ Holiday : int 1 0 0 0 0 0 0 0 0 0 ... 92 | $ Snow : num 0 0 0 0 0 0 0 0 0 0 ... 93 | ``` 94 | >You have now read the data from SQL Server to R and explored it. 95 | 96 | ## Step 2.3 Prepare the data 97 | 98 | Often times, the data needs to be prepared and cleaned before we start calling the functions. In this tutorial, most of the preparations have already been done. 99 | We are just going to change the type of 3 columns to factors. 100 | 101 | ```r 102 | #Changing the three factor columns to factor types 103 | #This helps when building the model because we are explicitly saying that these values are categorical 104 | rentaldata$Holiday <- factor(rentaldata$Holiday); 105 | rentaldata$Snow <- factor(rentaldata$Snow); 106 | rentaldata$WeekDay <- factor(rentaldata$WeekDay); 107 | 108 | #Visualize the dataset after the change 109 | str(rentaldata); 110 | ``` 111 | 112 | ```results 113 | data.frame': 453 obs. of 7 variables: 114 | $ Year : int 2014 2014 2013 2014 2014 2015 2013 2014 2013 2015 ... 115 | $ Month : num 1 2 3 3 4 2 4 3 4 3 ... 116 | $ Day : num 20 13 10 31 24 11 28 8 5 29 ... 117 | $ RentalCount: num 445 40 456 38 23 42 310 240 22 360 ... 118 | $ WeekDay : Factor w/ 7 levels "1","2","3","4",..: 2 5 1 2 5 4 1 7 6 1 ... 119 | $ Holiday : Factor w/ 2 levels "0","1": 2 1 1 1 1 1 1 1 1 1 ... 120 | $ Snow : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ... 121 | ``` 122 | >The data is now prepared for training. 123 | 124 | ## Step 2.4 Train a model 125 | In order to predict, we have to first find a function (model) that best describes the dependency between the variables in our dataset. This step is called training the model. The training dataset will be a subset of the entire dataset. 126 | We are going to create two different models and see which one is predicting more accurately. 127 | 128 | ```r 129 | #Now let's split the dataset into 2 different sets 130 | #One set for training the model and the other for validating it 131 | train_data = rentaldata[rentaldata$Year < 2015,]; 132 | test_data = rentaldata[rentaldata$Year == 2015,]; 133 | 134 | #Use this column to check the quality of the prediction against actual values 135 | actual_counts <- test_data$RentalCount; 136 | 137 | #Model 1: Use rxLinMod to create a linear regression model. We are training the data using the training data set 138 | model_linmod <- rxLinMod(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = train_data); 139 | 140 | #Model 2: Use rxDTree to create a decision tree model. We are training the data using the training data set 141 | model_dtree <- rxDTree(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = train_data); 142 | ``` 143 | >Now we have trained and created two different models! Let's use them to predict and see which model is the most accurate. 144 | 145 | 146 | 147 | ## Step 2.5 prediction 148 | We are now going to use a predict function to predict the Rental Counts using our two models. Finding the right type of model for a specific problem requires some experimentation. 149 | This [cheat sheet](https://azure.microsoft.com/en-us/documentation/articles/machine-learning-algorithm-choice/#the-machine-learning-algorithm-cheat-sheet) can be nice to have as a guide. 150 | 151 | ```r 152 | #Use the models we just created to predict using the test data set. 153 | #That enables us to compare actual values of RentalCount from the two models and compare to the actual values in the test data set 154 | predict_linmod <- rxPredict(model_linmod, test_data, writeModelVars = TRUE, extraVarsToWrite = c("Year")); 155 | 156 | predict_dtree <- rxPredict(model_dtree, test_data, writeModelVars = TRUE, extraVarsToWrite = c("Year")); 157 | 158 | #Look at the top rows of the two prediction data sets. 159 | head(predict_linmod); 160 | head(predict_dtree); 161 | ``` 162 | 163 | ```results 164 | RentalCount_Pred RentalCount Month Day WeekDay Snow Holiday 165 | 1 27.45858 42 2 11 4 0 0 166 | 2 387.29344 360 3 29 1 0 0 167 | 3 16.37349 20 4 22 4 0 0 168 | 4 31.07058 42 3 6 6 0 0 169 | 5 463.97263 405 2 28 7 1 0 170 | 6 102.21695 38 1 12 2 1 0 171 | RentalCount_Pred RentalCount Month Day WeekDay Snow Holiday 172 | 1 40.0000 42 2 11 4 0 0 173 | 2 332.5714 360 3 29 1 0 0 174 | 3 27.7500 20 4 22 4 0 0 175 | 4 34.2500 42 3 6 6 0 0 176 | 5 645.7059 405 2 28 7 1 0 177 | 6 40.0000 38 1 12 2 1 0 178 | ``` 179 | 180 | >Congrats you just created two models with R! 181 | 182 | ## Step 2.6 Compare results 183 | 184 | Now let's see which of the models gives the best predictions. To be able to find out, we are going to plot the difference between the predicted and actual values. 185 | R is a great language for quickly and easily visualizing data. We are going to use a basic plotting function to plot 2 graphs. 186 | 187 | 188 | ```r 189 | #Now we will use the plotting functionality in R to viusalize the results from the predictions 190 | #We are plotting the difference between actual and predicted values for both models to compare accuracy 191 | par(mfrow = c(2, 1)); 192 | plot(predict_linmod$RentalCount_Pred - predict_linmod$RentalCount, main = "Difference between actual and predicted. rxLinmod"); 193 | plot(predict_dtree$RentalCount_Pred - predict_dtree$RentalCount, main = "Difference between actual and predicted. rxDTree"); 194 | ``` 195 | 196 | ![alt text](https://sqlchoice.blob.core.windows.net/sqlchoice/RLANG_CompareModels.JPG "Comparing the two models") 197 | 198 | It looks like the decision tree model is more accurate. We have a quite accurate predictor and we feel confident to use it to predict 199 | what is going to happen on a given situation in the future. 200 | 201 | > Congrats, you have decided on which model to use! Let us now deploy our R code by moving it to SQL Server. 202 | -------------------------------------------------------------------------------- /pages/R/rentalprediction/step-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: R 4 | title: Build a predictive model 5 | permalink: /R/rentalprediction/step/3 6 | --- 7 | 8 | 9 | 10 | >In this section, we will move the R code we just wrote to SQL Server and deploy our predictive model with the help of SQL Server Machine Learning Services. 11 | >To deploy a model, you store the model in a hosting environment (like a database) and implement a prediction function that uses the model to predict. That function can be called from applications. 12 | 13 | SQL Server ML Services enables you to train and test predictive models in the context of SQL Server. You author T-SQL programs that contain embedded R scripts, and the SQL Server database engine takes care of the execution. Because it executes in SQL Server, your models can easily be trained against data stored in the database. 14 | To deploy, you store your model in the database and create a stored procedure that predicts using the model. 15 | 16 | 17 | ## Step 3.1 Create a table for storing the model 18 | 19 | In SSMS, launch a new query window and run the following T-SQL script: 20 | 21 | ```sql 22 | USE TutorialDB; 23 | DROP TABLE IF EXISTS rental_rx_models; 24 | GO 25 | CREATE TABLE rental_rx_models ( 26 | model_name VARCHAR(30) NOT NULL DEFAULT('default model') PRIMARY KEY, 27 | model VARBINARY(MAX) NOT NULL 28 | ); 29 | GO 30 | ``` 31 | 32 | ## Step 3.2 Create stored procedure for generating the model 33 | 34 | We are now going to create a stored procedure in SQL Server to use the R code we wrote in the previous module and generate the rxDTree model inside the database. 35 | The R code will be embedded in the TSQL statement. 36 | 37 | 1.Create the stored procedure 38 | 39 | ```sql 40 | -- Stored procedure that trains and generates an R model using the rental_data and a decision tree algorithm 41 | DROP PROCEDURE IF EXISTS generate_rental_rx_model; 42 | go 43 | CREATE PROCEDURE generate_rental_rx_model (@trained_model varbinary(max) OUTPUT) 44 | AS 45 | BEGIN 46 | EXECUTE sp_execute_external_script 47 | @language = N'R' 48 | , @script = N' 49 | require("RevoScaleR"); 50 | 51 | rental_train_data$Holiday = factor(rental_train_data$Holiday); 52 | rental_train_data$Snow = factor(rental_train_data$Snow); 53 | rental_train_data$WeekDay = factor(rental_train_data$WeekDay); 54 | 55 | #Create a dtree model and train it using the training data set 56 | model_dtree <- rxDTree(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = rental_train_data); 57 | #Before saving the model to the DB table, we need to serialize it 58 | trained_model <- as.raw(serialize(model_dtree, connection=NULL));' 59 | 60 | , @input_data_1 = N'select "RentalCount", "Year", "Month", "Day", "WeekDay", "Snow", "Holiday" from dbo.rental_data where Year < 2015' 61 | , @input_data_1_name = N'rental_train_data' 62 | , @params = N'@trained_model varbinary(max) OUTPUT' 63 | , @trained_model = @trained_model OUTPUT; 64 | END; 65 | GO 66 | ``` 67 | 1.Save the model to a table 68 | ```sql 69 | -- Save model to table 70 | TRUNCATE TABLE rental_rx_models; 71 | 72 | DECLARE @model VARBINARY(MAX); 73 | EXEC generate_rental_rx_model @model OUTPUT; 74 | 75 | INSERT INTO rental_rx_models (model_name, model) VALUES('rxDTree', @model); 76 | 77 | SELECT * FROM rental_rx_models; 78 | ``` 79 | 80 | The model is now saved in the database as a binary object. 81 | 82 | ## Step 3.2 Create stored procedure for prediction 83 | 84 | We are now very close to deploying our predicting model so that we can consume it from our applications. 85 | This last step includes creating a stored procedure that uses our model to predict the rental count for new data. 86 | 87 | 1.Create a stored procedure that predicts using our model 88 | 89 | ```sql 90 | --Stored procedure that takes model name and new data as input parameters and predicts the rental count for the new data 91 | DROP PROCEDURE IF EXISTS predict_rentalcount_new; 92 | GO 93 | CREATE PROCEDURE predict_rentalcount_new (@model VARCHAR(100),@q NVARCHAR(MAX)) 94 | AS 95 | BEGIN 96 | DECLARE @rx_model VARBINARY(MAX) = (SELECT model FROM rental_rx_models WHERE model_name = @model); 97 | EXECUTE sp_execute_external_script 98 | @language = N'R' 99 | , @script = N' 100 | require("RevoScaleR"); 101 | 102 | #The InputDataSet contains the new data passed to this stored proc. We will use this data to predict. 103 | rentals = InputDataSet; 104 | 105 | #Convert types to factors 106 | rentals$Holiday = factor(rentals$Holiday); 107 | rentals$Snow = factor(rentals$Snow); 108 | rentals$WeekDay = factor(rentals$WeekDay); 109 | 110 | #Before using the model to predict, we need to unserialize it 111 | rental_model = unserialize(rx_model); 112 | 113 | #Call prediction function 114 | rental_predictions = rxPredict(rental_model, rentals);' 115 | , @input_data_1 = @q 116 | , @output_data_1_name = N'rental_predictions' 117 | , @params = N'@rx_model varbinary(max)' 118 | , @rx_model = @rx_model 119 | WITH RESULT SETS (("RentalCount_Predicted" FLOAT)); 120 | 121 | END; 122 | GO 123 | ``` 124 | 125 | 1.Execute the stored procedure to predict rental count for new data 126 | 127 | ```sql 128 | --Execute the predict_rentals stored proc and pass the modelname and a query string with a set of features we want to use to predict the rental count 129 | EXEC dbo.predict_rentalcount_new @model = 'rxDTree', 130 | @q ='SELECT CONVERT(INT, 3) AS Month, CONVERT(INT, 24) AS Day, CONVERT(INT, 4) AS WeekDay, CONVERT(INT, 1) AS Snow, CONVERT(INT, 1) AS Holiday'; 131 | GO 132 | ``` 133 | 134 | ## Step 3.3 Predict using native scoring (New!) 135 | In SQL Server 2017, we are introducing a native predict function in TSQL. The native PREDICT function allows you to perform faster scoring using certain RevoScaleR or revoscalepy models using a SQL query without invoking the R or Python runtime. The following code sample shows how you can train a model in R using RevoscaleR "Rx" functions, save the model to a table in the DB and predict using [native scoring](https://docs.microsoft.com/en-us/sql/advanced-analytics/sql-native-scoring). 136 | 137 | ```sql 138 | USE TutorialDB; 139 | 140 | --STEP 1 - Setup model table for storing the model 141 | DROP TABLE IF EXISTS rental_models; 142 | GO 143 | CREATE TABLE rental_models ( 144 | model_name VARCHAR(30) NOT NULL DEFAULT('default model'), 145 | lang VARCHAR(30), 146 | model VARBINARY(MAX), 147 | native_model VARBINARY(MAX), 148 | PRIMARY KEY (model_name, lang) 149 | 150 | ); 151 | GO 152 | 153 | 154 | --STEP 2 - Train model using RevoscaleR 155 | DROP PROCEDURE IF EXISTS generate_rental_R_native_model; 156 | go 157 | CREATE PROCEDURE generate_rental_R_native_model (@model_type varchar(30), @trained_model varbinary(max) OUTPUT) 158 | AS 159 | BEGIN 160 | EXECUTE sp_execute_external_script 161 | @language = N'R' 162 | , @script = N' 163 | require("RevoScaleR") 164 | 165 | rental_train_data$Holiday = factor(rental_train_data$Holiday); 166 | rental_train_data$Snow = factor(rental_train_data$Snow); 167 | rental_train_data$WeekDay = factor(rental_train_data$WeekDay); 168 | 169 | if(model_type == "linear") { 170 | #Create a dtree model and train it using the training data set 171 | model_dtree <- rxDTree(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = rental_train_data); 172 | trained_model <- rxSerializeModel(model_dtree, realtimeScoringOnly = TRUE); 173 | } 174 | 175 | if(model_type == "dtree") { 176 | model_linmod <- rxLinMod(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = rental_train_data); 177 | #Before saving the model to the DB table, we need to serialize it. This time, as a native scoring model 178 | trained_model <- rxSerializeModel(model_linmod, realtimeScoringOnly = TRUE); 179 | } 180 | ' 181 | 182 | , @input_data_1 = N'select "RentalCount", "Year", "Month", "Day", "WeekDay", "Snow", "Holiday" from dbo.rental_data where Year < 2015' 183 | , @input_data_1_name = N'rental_train_data' 184 | , @params = N'@trained_model varbinary(max) OUTPUT, @model_type varchar(30)' 185 | , @model_type = @model_type 186 | , @trained_model = @trained_model OUTPUT; 187 | END; 188 | GO 189 | 190 | --STEP 3 - Save model to table 191 | 192 | --Line of code to empty table with models 193 | --TRUNCATE TABLE rental_models; 194 | 195 | --Save Linear model to table 196 | DECLARE @model VARBINARY(MAX); 197 | EXEC generate_rental_R_native_model "linear", @model OUTPUT; 198 | INSERT INTO rental_models (model_name, native_model, lang) VALUES('linear_model', @model, 'R'); 199 | 200 | --Save DTree model to table 201 | DECLARE @model2 VARBINARY(MAX); 202 | EXEC generate_rental_R_native_model "dtree", @model2 OUTPUT; 203 | INSERT INTO rental_models (model_name, native_model, lang) VALUES('dtree_model', @model2, 'R'); 204 | 205 | -- Look at the models in the table 206 | SELECT * FROM rental_models; 207 | 208 | GO 209 | -- STEP 4 - Use the native PREDICT (native scoring) to predict number of rentals for both models 210 | --Now lets predict using native scoring with linear model 211 | DECLARE @model VARBINARY(MAX) = (SELECT TOP(1) native_model FROM dbo.rental_models WHERE model_name = 'linear_model' AND lang = 'R'); 212 | SELECT d.*, p.* FROM PREDICT(MODEL = @model, DATA = dbo.rental_data AS d) WITH(RentalCount_Pred float) AS p; 213 | GO 214 | 215 | --Native scoring with dtree model 216 | DECLARE @model VARBINARY(MAX) = (SELECT TOP(1) native_model FROM dbo.rental_models WHERE model_name = 'dtree_model' AND lang = 'R'); 217 | SELECT d.*, p.* FROM PREDICT(MODEL = @model, DATA = dbo.rental_data AS d) WITH(RentalCount_Pred float) AS p; 218 | GO 219 | 220 | ``` 221 | 222 | > Congrats you just deployed a predictive model in SQL Server using R! 223 | -------------------------------------------------------------------------------- /pages/python/customerclustering/step-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: Python 4 | title: Perform customer clustering 5 | permalink: /python/customerclustering/ 6 | redirect_from: 7 | - /Python/ 8 | - /Python/customerclustering/step/ 9 | - /Python/customerclustering/step/1 10 | --- 11 | 12 | 13 | > In this tutorial, we are going to get ourselves familiar with clustering. **Clustering** can be explained as organizing data into groups where members of a group are similar in some way. 14 | We will be using the **Kmeans** algorithm to perform the clustering of customers. This can for example be used to target a specific group of customers for marketing efforts. 15 | Kmeans clustering is an unsupervised learning algorithm that tries to group data based on similarities. Unsupervised learning means that there is no outcome to be predicted, and the algorithm just tries to find patterns in the data. 16 | You will learn how to perform clustering using Kmeans and analyze the results. We will also cover how you can deploy a clustering solution using SQL Server. 17 | You can copy code as you follow the tutorial. All code is also available on [GitHub](https://github.com/Microsoft/sql-server-samples/tree/master/samples/features/machine-learning-services/python/getting-started). 18 | 19 | 20 | ## Step 1.1 Install SQL Server with in-database R / Machine Learning Services 21 | {% include partials/install_sql_server_windows_ML.md %} 22 | 23 | ## Step 1.2 Install SQL Server Management Studio (SSMS) 24 | Download and install SQL Server Management studio: [SSMS](https://msdn.microsoft.com/en-us/library/mt238290.aspx) 25 | 26 | >Now you have installed a tool you can use to easily manage your database objects and scripts. 27 | 28 | 29 | ## Step 1.3 Enable external script execution 30 | Run SSMS and open a new query window. Then execute the script below to enable your instance to run R scripts in SQL Server. 31 | 32 | ```sql 33 | EXEC sp_configure 'external scripts enabled', 1; 34 | RECONFIGURE WITH OVERRIDE 35 | ``` 36 | You can read more about configuring Machine Learning Services [here](https://docs.microsoft.com/en-us/sql/advanced-analytics/r-services/set-up-sql-server-r-services-in-database). 37 | **Don't forget to restart your SQL Server Instance after the configuration!** You can restart in SSMS by right clicking on the instance name in the Object Explorer and choose *Restart*. 38 | 39 | Optional: If you want, you can also [download SSMS custom reports](https://github.com/Microsoft/sql-server-samples/blob/master/samples/features/r-services/ssms-custom-reports/R%20Services%20-%20Configuration.rdl) available on github. 40 | The report "R Services - Configuration.rdl" for example provides an overview of the R runtime parameters and gives you an option to configure your instance with a button click. 41 | To import a report in SSMS, right click on Server Objects in the SSMS Object Explorer and choose Reports -> Custom reports. Upload the .rdl file. 42 | 43 | >Now you have enabled external script execution so that you can run Python code inside SQL Server! 44 | 45 | ## Step 1.4 Install and configure your Python development environment 46 | 1.You need to install a Python IDE. Here are some suggestions: 47 | 48 | *Python Tools for Visual Studio (PTVS) [Download](https://microsoft.github.io/PTVS) 49 | 50 | *VS Code [(download)](https://code.visualstudio.com/download) with the [Python Extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python) and the [mssql extension](https://marketplace.visualstudio.com/items?itemName=ms-mssql.mssql) 51 | 52 | *PyCharm [Download](https://www.jetbrains.com/pycharm/) 53 | 54 | 55 | ## Step 1.5 Install remote Python client libraries 56 | 57 | **Note!!! To be able to use some of the functions in this tutorial, you need to have the revoscalepy package.** 58 | 59 | Follow instructions here to learn how you can install Python client libaries for remote execution against SQL Server ML Services: 60 | 61 | [How to install Python client libraries](]https://docs.microsoft.com/en-us/machine-learning-server/install/python-libraries-interpreter) 62 | 63 | 64 | > Terrific, now your SQL Server instance is able to host and run R code and you have the necessary development tools installed and configured! The next section will walk you through how to do clustering using R. 65 | 66 | -------------------------------------------------------------------------------- /pages/python/customerclustering/step-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: Python 4 | title: Perform customer clustering 5 | permalink: /python/customerclustering/step/2 6 | --- 7 | 8 | 9 | >After getting SQL Server 2017 with Machine Learning Services installed and your Python IDE up on your machine, you can now proceed and perform clustering using Python. 10 | 11 | >Python is a programming language that can be used for machine learning and predictive analytics. 12 | 13 | >In this specific scenario, we have a store and we want to group customers based on their order and return behaviour. 14 | This information will help us target marketing efforts towards certain groups of customers. Before we go into how you can use R to perform this type of customer grouping using clustering in SQL Server 2017, we will look at the scenario in Python. 15 | 16 | 17 | ## Step 2.1 Load the sample data 18 | 19 | **Restore the sample DB** 20 | The dataset used in this tutorial is hosted in several SQL Server tables.The tables contain purchasing and return data based on orders. 21 | 22 | 1. Download the backup (.bak) file [here](https://sqlchoice.blob.core.windows.net/sqlchoice/static/tpcxbb_1gb.bak), and save it on a location that SQL Server can access. 23 | For example in the folder where SQL Server is installed. 24 | Sample path: C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup 25 | 26 | 27 | 2. Once you have the file saved, open SSMS and a new query window to run the following commands to restore the DB. 28 | Make sure to modify the file paths and server name in the script. 29 | 30 | ```sql 31 | USE master; 32 | GO 33 | RESTORE DATABASE tpcxbb_1gb 34 | FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\tpcxbb_1gb.bak' 35 | WITH 36 | MOVE 'tpcxbb_1gb' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\tpcxbb_1gb.mdf' 37 | ,MOVE 'tpcxbb_1gb_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\tpcxbb_1gb.ldf'; 38 | GO 39 | ``` 40 | 41 | You should now be able to see the database and tables store_sales and store_returns in the Object Explorer in SSMS. 42 | You can also verify this by querying the tables in SSMS. Open a new query window and select the following. 43 | 44 | ```sql 45 | USE tpcxbb_1gb; 46 | SELECT TOP (100) * FROM [dbo].[store_sales]; 47 | SELECT TOP (100) * FROM [dbo].[store_returns]; 48 | ``` 49 | 50 | >You now have the database and the data to perform clustering. 51 | 52 | 53 | ## Step 2.2 Access the data from SQL Server using Python 54 | 55 | Loading data from SQL Server to Python is easy. So let's try it out. 56 | 57 | Open a new Python Script in your Python IDE and run the following script. 58 | Just don't forget to replace "MYSQLSERVER" with the name of your database instance. 59 | 60 | In the query we are using to select data from SQL Server, we are separating customers along the following dimensions: 61 | - *return frequency* 62 | - *return order ratio (total number of orders partially or fully returned versus the total number of orders)* 63 | - *return item ratio (total number of items returned versus the number of items purchased)* 64 | - *return amount ration (total monetary amount of items returned versus the amount purchased)* 65 | 66 | ```Python 67 | # Load packages. 68 | import matplotlib.pyplot as plt 69 | import numpy as np 70 | import pandas as pd 71 | import revoscalepy as revoscale 72 | from scipy.spatial import distance as sci_distance 73 | from sklearn import cluster as sk_cluster 74 | 75 | 76 | 77 | def perform_clustering(): 78 | ################################################################################################ 79 | 80 | ## Connect to DB and select data 81 | 82 | ################################################################################################ 83 | 84 | # Connection string to connect to SQL Server named instance. 85 | conn_str = 'Driver=SQL Server;Server=localhost;Database=tpcxbb_1gb;Trusted_Connection=True;' 86 | 87 | input_query = '''SELECT 88 | ss_customer_sk AS customer, 89 | ROUND(COALESCE(returns_count / NULLIF(1.0*orders_count, 0), 0), 7) AS orderRatio, 90 | ROUND(COALESCE(returns_items / NULLIF(1.0*orders_items, 0), 0), 7) AS itemsRatio, 91 | ROUND(COALESCE(returns_money / NULLIF(1.0*orders_money, 0), 0), 7) AS monetaryRatio, 92 | COALESCE(returns_count, 0) AS frequency 93 | FROM 94 | ( 95 | SELECT 96 | ss_customer_sk, 97 | -- return order ratio 98 | COUNT(distinct(ss_ticket_number)) AS orders_count, 99 | -- return ss_item_sk ratio 100 | COUNT(ss_item_sk) AS orders_items, 101 | -- return monetary amount ratio 102 | SUM( ss_net_paid ) AS orders_money 103 | FROM store_sales s 104 | GROUP BY ss_customer_sk 105 | ) orders 106 | LEFT OUTER JOIN 107 | ( 108 | SELECT 109 | sr_customer_sk, 110 | -- return order ratio 111 | count(distinct(sr_ticket_number)) as returns_count, 112 | -- return ss_item_sk ratio 113 | COUNT(sr_item_sk) as returns_items, 114 | -- return monetary amount ratio 115 | SUM( sr_return_amt ) AS returns_money 116 | FROM store_returns 117 | GROUP BY sr_customer_sk ) returned ON ss_customer_sk=sr_customer_sk''' 118 | 119 | 120 | # Define the columns we wish to import. 121 | column_info = { 122 | "customer": {"type": "integer"}, 123 | "orderRatio": {"type": "integer"}, 124 | "itemsRatio": {"type": "integer"}, 125 | "frequency": {"type": "integer"} 126 | } 127 | 128 | ``` 129 | Results from the query are returned to Python using the revoscalepy RxSqlServerData function. 130 | This is also where we provide column info, to make sure that the types are correctly transferred. 131 | 132 | ```Python 133 | data_source = revoscale.RxSqlServerData(sql_query=input_query, column_Info=column_info, 134 | connection_string=conn_str) 135 | revoscale.RxInSqlServer(connection_string=conn_str, num_tasks=1, auto_cleanup=False) 136 | # import data source and convert to pandas dataframe. 137 | customer_data = pd.DataFrame(revoscale.rx_import(data_source)) 138 | print("Data frame:", customer_data.head(n=5)) 139 | ``` 140 | 141 | ```results 142 | Rows Read: 37336, Total Rows Processed: 37336, Total Chunk Time: 0.172 seconds 143 | Data frame: customer orderRatio itemsRatio monetaryRatio frequency 144 | 0 29727.0 0.000000 0.000000 0.000000 0 145 | 1 97643.0 0.068182 0.078176 0.037034 3 146 | 2 57247.0 0.000000 0.000000 0.000000 0 147 | 3 32549.0 0.086957 0.068657 0.031281 4 148 | 4 2040.0 0.000000 0.000000 0.000000 0 149 | ``` 150 | 151 | >You have now read the data from SQL Server to Python. 152 | 153 | ## Step 2.3 Determine number of clusters 154 | 155 | Using the clustering algorithm **Kmeans**, is one of the simplest and most well known ways of grouping data. 156 | Now that we have our selected data, we can group the data into clusters using the iterative data mining algorithm called Kmeans. 157 | 158 | The algorithm accepts two inputs: The data itself, and a predefined number "k", the number of clusters. 159 | The output is k clusters with input data partitioned among them. 160 | 161 | The goal of K-means is to group the items into k clusters such that all items in same cluster are as similar to each other as possible. And items not in same cluster are as different as possible. 162 | It uses the distance measures to calculate similarity and dissimilarity. 163 | 164 | This is how the algorithm works: 165 | 166 | 1. It randomly chooses k points and make them the initial centroids (each cluster has a centroid which basically is the "center" of the cluster) 167 | 2. For each point, it finds the nearest centroid and assigns the point to the cluster associated with the nearest centroid 168 | 3. Updates the centroid of each cluster based on members in that cluster. Typically, a new centroid will be the average of all members in the cluster 169 | 4. Repeats steps 2 and 3, until the clusters are stable 170 | 171 | The number of clusters has to be predefined and the quality of the clusters is heavily dependent on the correctness of the k value specified. 172 | You could just randomly pick a number of clusters, run Kmeans and iterate your way to a good number. 173 | Or we can use Python to evaluate which number of clusters is best for our dataset. Let's determine the number of clusters using Python and the Elbow method! 174 | 175 | ```Python 176 | ################################################################################################ 177 | 178 | ## Determine number of clusters using the Elbow method 179 | 180 | ################################################################################################ 181 | 182 | cdata = customer_data 183 | K = range(1, 20) 184 | KM = (sk_cluster.KMeans(n_clusters=k).fit(cdata) for k in K) 185 | centroids = (k.cluster_centers_ for k in KM) 186 | 187 | D_k = (sci_distance.cdist(cdata, cent, 'euclidean') for cent in centroids) 188 | dist = (np.min(D, axis=1) for D in D_k) 189 | avgWithinSS = [sum(d) / cdata.shape[0] for d in dist] 190 | plt.plot(K, avgWithinSS, 'b*-') 191 | plt.grid(True) 192 | plt.xlabel('Number of clusters') 193 | plt.ylabel('Average within-cluster sum of squares') 194 | plt.title('Elbow for KMeans clustering') 195 | plt.show() 196 | ``` 197 | 198 | ![Elbow graph](https://sqlchoice.blob.core.windows.net/sqlchoice/static/images/Python_Elbow_Graph.png) 199 | Finding the right number of clusters using an elbow graph 200 | 201 | Based on the graph, it looks like *k = 4* would be a good value to try. That will group our customers into 4 clusters. 202 | 203 | >Now we have derived the number of clusters to use when clustering! 204 | 205 | 206 | ## Step 2.4 Perform Clustering 207 | It is now time to use Kmeans. In this sample, we will be using the KMeans function from the sklearn package. 208 | 209 | ```Python 210 | ################################################################################################ 211 | ## Perform clustering using Kmeans 212 | ################################################################################################ 213 | 214 | # It looks like k=4 is a good number to use based on the elbow graph. 215 | n_clusters = 4 216 | 217 | means_cluster = sk_cluster.KMeans(n_clusters=n_clusters, random_state=111) 218 | columns = ["orderRatio", "itemsRatio", "monetaryRatio", "frequency"] 219 | est = means_cluster.fit(customer_data[columns]) 220 | clusters = est.labels_ 221 | customer_data['cluster'] = clusters 222 | 223 | # Print some data about the clusters: 224 | 225 | # For each cluster, count the members. 226 | for c in range(n_clusters): 227 | cluster_members=customer_data[customer_data['cluster'] == c][:] 228 | print('Cluster{}(n={}):'.format(c, len(cluster_members))) 229 | print('-'* 17) 230 | 231 | # Print mean values per cluster. 232 | print(customer_data.groupby(['cluster']).mean()) 233 | 234 | 235 | perform_clustering() 236 | ``` 237 | 238 | >Great, now you have performed clustering in Python! 239 | 240 | ## Step 2.5 Analyze clusters 241 | 242 | Now that we have done the clustering using Kmeans, we need to analyze the clusters and see if we can learn anything from that. 243 | The clustering mean values and the cluster sizes we just printed could tell us something about our data. 244 | 245 | ```results 246 | 247 | Cluster0(n=31675): 248 | ------------------- 249 | Cluster1(n=4989): 250 | ------------------- 251 | Cluster2(n=1): 252 | ------------------- 253 | Cluster3(n=671): 254 | ------------------- 255 | 256 | customer orderRatio itemsRatio monetaryRatio frequency 257 | cluster 258 | 0 50854.809882 0.000000 0.000000 0.000000 0.000000 259 | 1 51332.535779 0.721604 0.453365 0.307721 1.097815 260 | 2 57044.000000 1.000000 2.000000 108.719154 1.000000 261 | 3 48516.023845 0.136277 0.078346 0.044497 4.271237 262 | ``` 263 | 264 | Focusing on the cluster mean values, it seems like we can actually interpret something. 265 | Just to refresh our memory, here are the definitions of our variables: 266 | 267 | * *frequency = return frequency* 268 | * *orderRatio = return order ratio (total number of orders partially or fully returned versus the total number of orders)* 269 | * *itemsRatio = return item ratio (total number of items returned versus the number of items purchased)* 270 | * *monetaryRatio = return amount ratio (total monetary amount of items returned versus the amount purchased)* 271 | 272 | Some examples of what the mean values tell us? 273 | 274 | * Well, cluster 0 (the largest cluster) seems to be a group of customers that are very inactive. All values are zero. 275 | * And cluster 3 seems to be a group that stands out in terms of return behaviour. 276 | 277 | Data mining using Kmeans often requires further analysis of the results, and further steps to better understand each cluster, 278 | but it provides some very good leads. Cluster 0 is a set of customers who are clearly not active. Perhaps we can target marketing efforts towards this group to trigger an interest for purchases? 279 | In the next step, we will query the database for the email addresses of customers in cluster 0, so that we can send a marketing email to them. 280 | 281 | > Congrats you just performed clustering in Python! Let us now deploy our Python code by moving it to SQL Server. 282 | -------------------------------------------------------------------------------- /pages/python/customerclustering/step-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: Python 4 | title: Perform customer clustering 5 | permalink: /python/customerclustering/step/3 6 | --- 7 | 8 | 9 | >In this section, we will move the Python code we just wrote into SQL Server and deploy our clustering with the help of SQL Server Machine Learning Services. 10 | 11 | >In order to perform clustering on a regular basis, as new customers are registering, we need to be able call our Python script from any App. 12 | To do that, we can simply delploy the Python Script in SQL Server. You basically put the Python script inside a SQL stored procedure in the database. A stored procedure is like a function, that takes parameters and can return results, and the good thing with these procedures is that they can be called from any application. 13 | 14 | 15 | ## Step 3.1 Create a stored procedure for clustering 16 | 17 | In SSMS, launch a new query window and run the following T-SQL script to create the stored procedure: 18 | 19 | ```sql 20 | USE [tpcxbb_1gb] 21 | CREATE procedure [dbo].[py_generate_customer_return_clusters] 22 | AS 23 | 24 | BEGIN 25 | DECLARE 26 | 27 | -- Input query to generate the purchase history & return metrics 28 | @input_query NVARCHAR(MAX) = N' 29 | SELECT 30 | ss_customer_sk AS customer, 31 | CAST( (ROUND(COALESCE(returns_count / NULLIF(1.0*orders_count, 0), 0), 7) ) AS FLOAT) AS orderRatio, 32 | CAST( (ROUND(COALESCE(returns_items / NULLIF(1.0*orders_items, 0), 0), 7) ) AS FLOAT) AS itemsRatio, 33 | CAST( (ROUND(COALESCE(returns_money / NULLIF(1.0*orders_money, 0), 0), 7) ) AS FLOAT) AS monetaryRatio, 34 | CAST( (COALESCE(returns_count, 0)) AS FLOAT) AS frequency 35 | FROM 36 | ( 37 | SELECT 38 | ss_customer_sk, 39 | -- return order ratio 40 | COUNT(distinct(ss_ticket_number)) AS orders_count, 41 | -- return ss_item_sk ratio 42 | COUNT(ss_item_sk) AS orders_items, 43 | -- return monetary amount ratio 44 | SUM( ss_net_paid ) AS orders_money 45 | FROM store_sales s 46 | GROUP BY ss_customer_sk 47 | ) orders 48 | LEFT OUTER JOIN 49 | ( 50 | SELECT 51 | sr_customer_sk, 52 | -- return order ratio 53 | count(distinct(sr_ticket_number)) as returns_count, 54 | -- return ss_item_sk ratio 55 | COUNT(sr_item_sk) as returns_items, 56 | -- return monetary amount ratio 57 | SUM( sr_return_amt ) AS returns_money 58 | FROM store_returns 59 | GROUP BY sr_customer_sk 60 | ) returned ON ss_customer_sk=sr_customer_sk 61 | ' 62 | 63 | EXEC sp_execute_external_script 64 | @language = N'Python' 65 | , @script = N' 66 | 67 | import pandas as pd 68 | from sklearn.cluster import KMeans 69 | 70 | #get data from input query 71 | customer_data = my_input_data 72 | 73 | #We concluded in step2 in the tutorial that 4 would be a good number of clusters 74 | n_clusters = 4 75 | 76 | #Perform clustering 77 | est = KMeans(n_clusters=n_clusters, random_state=111).fit(customer_data[["orderRatio","itemsRatio","monetaryRatio","frequency"]]) 78 | clusters = est.labels_ 79 | customer_data["cluster"] = clusters 80 | 81 | OutputDataSet = customer_data 82 | ' 83 | , @input_data_1 = @input_query 84 | , @input_data_1_name = N'my_input_data' 85 | with result sets (("Customer" int, "orderRatio" float,"itemsRatio" float,"monetaryRatio" float,"frequency" float,"cluster" float)); 86 | END; 87 | GO 88 | ``` 89 | 90 | >You have now created a stored procedure that contains the Python script for clustering. 91 | 92 | 93 | ## Step 3.2 Perform clustering in SQL Server 94 | 95 | We are now going to execute the stored procedure and save the clustering results in a table in SQL Server. 96 | 97 | ```sql 98 | --Creating a table for storing the clustering data 99 | DROP TABLE IF EXISTS [dbo].[py_customer_clusters]; 100 | GO 101 | --Create a table to store the predictions in 102 | CREATE TABLE [dbo].[py_customer_clusters]( 103 | [Customer] [bigint] NULL, 104 | [OrderRatio] [float] NULL, 105 | [itemsRatio] [float] NULL, 106 | [monetaryRatio] [float] NULL, 107 | [frequency] [float] NULL, 108 | [cluster] [int] NULL, 109 | ) ON [PRIMARY] 110 | GO 111 | 112 | --Execute the clustering and insert results into table 113 | INSERT INTO py_customer_clusters 114 | EXEC [dbo].[py_generate_customer_return_clusters]; 115 | 116 | -- Select contents of the table 117 | SELECT * FROM py_customer_clusters; 118 | ``` 119 | 120 | >Congrats, you have performed clustering with R inside SQL Server! 121 | 122 | 123 | ## Step 3.3 Why is it useful to deploy this in SQL Server? 124 | 125 | We now have the clustering implemented in SQL Server. Why is that useful? 126 | 127 | Well, imagine that you need to perform clustering on you cutomer data on a regular basis as new customers sign up to keep an updated understanding of customer behavior. In this example, we might want to send out promotion emails and can select the email addresses of customers in cluster 3 to send out a promotion. 128 | 129 | You can also schedule jobs that run the stored procedure and automatically send the results to for example a CRM application or a reporting tool. 130 | 131 | The code below is selecting the email addresses of customers in cluster 0, for a promotion campaign intending to activate this group of customers: 132 | 133 | ```sql 134 | USE [tpcxbb_1gb] 135 | --Get email addresses of customers in cluster 0 for a promotion campaign 136 | SELECT customer.[c_email_address], customer.c_customer_sk 137 | FROM dbo.customer 138 | JOIN 139 | [dbo].[py_customer_clusters] as c 140 | ON c.Customer = customer.c_customer_sk 141 | WHERE c.cluster = 0 142 | ``` 143 | 144 | > Congrats, you have now performed clustering in SQL Server with Python using SQL Server Machine Learning Services! 145 | -------------------------------------------------------------------------------- /pages/python/rentalprediction/step-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: Python 4 | title: Build a predictive model 5 | permalink: /python/rentalprediction/ 6 | redirect_from: 7 | - /python/ 8 | - /python/rentalprediction/step/ 9 | - /python/rentalprediction/step/1 10 | --- 11 | 12 | >Predictive modeling is a powerful way to add intelligence to your application. It enables applications to predict outcomes against new data. 13 | The act of incorporating predictive analytics into your applications involves two major phases: **model training** and **model deployment** 14 | 15 | >In this tutorial, you will learn how to create a predictive model in Python and deploy it with SQL Server 2017 Machine Learning Services, **RC1 and above**. 16 | 17 | >You can copy code as you follow this tutorial. All code is also available on [github](https://github.com/Microsoft/sql-server-samples/tree/master/samples/features/machine-learning-services/python/getting-started/rental-prediction). 18 | 19 | ## Step 1.1 Install SQL Server with in-database Machine Learning Services 20 | {% include partials/install_sql_server_windows_ML.md %} 21 | 22 | ## Step 1.2 Install SQL Server Management Studio (SSMS) 23 | Download and install SQL Server Management studio: [SSMS](https://msdn.microsoft.com/en-us/library/mt238290.aspx) 24 | 25 | >Now you have installed a tool you can use to easily manage your database objects and scripts. 26 | 27 | 28 | ## Step 1.3 Enable external script execution 29 | Run SSMS and open a new query window. Then execute the script below to enable your instance to run Python scripts in SQL Server. 30 | 31 | ```sql 32 | EXEC sp_configure 'external scripts enabled', 1; 33 | RECONFIGURE WITH OVERRIDE 34 | ``` 35 | You can read more about configuring Machine Learning Services [here](https://docs.microsoft.com/en-us/sql/advanced-analytics/r-services/set-up-sql-server-r-services-in-database). 36 | **Don't forget to restart your SQL Server Instance after the configuration!** You can restart in SSMS by right clicking on the instance name in the Object Explorer and choose *Restart*. 37 | 38 | 39 | >Now you have enabled external script execution so that you can run Python code inside SQL Server! 40 | 41 | ## Step 1.4 Install and configure your Python development environment 42 | 1.You need to install a Python IDE. Here are some suggestions: 43 | 44 | *Python Tools for Visual Studio (PTVS) [Download](https://microsoft.github.io/PTVS) 45 | 46 | *VS Code [(download)](https://code.visualstudio.com/download) with the [Python Extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python) and the [mssql extension](https://marketplace.visualstudio.com/items?itemName=ms-mssql.mssql) 47 | 48 | *PyCharm [Download](https://www.jetbrains.com/pycharm/) 49 | 50 | 51 | ## Step 1.5 Install remote Python client libraries 52 | 53 | **Note!!! To be able to use some of the functions in this tutorial, you need to have the revoscalepy package.** 54 | 55 | Follow instructions here to learn how you can install Python client libaries for remote execution against SQL Server ML Services: 56 | 57 | [How to install Python client libraries](]https://docs.microsoft.com/en-us/machine-learning-server/install/python-libraries-interpreter) 58 | 59 | >Terrific, now your SQL Server instance is able to host and run Python code and you have the necessary development tools installed and configured! 60 | The next section will walk you through creating a predictive model using Python. 61 | 62 | -------------------------------------------------------------------------------- /pages/python/rentalprediction/step-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: Python 4 | title: Build a predictive model 5 | permalink: /python/rentalprediction/step/2 6 | --- 7 | 8 | 9 | >After getting SQL Server with ML Services installed and your Python IDE configured on your machine, you can now proceed to **train** a predictive model with Python. 10 | 11 | >In this specific scenario, we own a ski rental business, and we want to predict the number of rentals that 12 | we will have on a future date. This information will help us to get ready from a stock, staff and facilities perspective. 13 | 14 | 15 | >During **model training**, you create and train a predictive model by showing it sample data along with the outcomes. Then you save this model so that you can use it later when you want to make predictions against new data. 16 | 17 | ## Step 2.1 Load the sample data 18 | 19 | **Restore the sample DB** 20 | The dataset used in this tutorial is hosted in a SQL Server table.The table contains rental data from previous years.

21 | 1. Download the backup (.bak) file [here](https://sqlchoice.blob.core.windows.net/sqlchoice/static/TutorialDB.bak), and save it on a location that SQL Server can access. 22 | For example in the folder where SQL Server is installed. 23 | Sample path: C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup 24 | 25 | 26 | 2.Once you have the file saved, open SSMS and a new query window to run the following commands to restore the DB. 27 | Make sure to modify the file paths and server name in the script. 28 | 29 | ```SQL 30 | USE master; 31 | GO 32 | RESTORE DATABASE TutorialDB 33 | FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\TutorialDB.bak' 34 | WITH 35 | MOVE 'TutorialDB' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\TutorialDB.mdf' 36 | ,MOVE 'TutorialDB_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\TutorialDB.ldf'; 37 | GO 38 | ``` 39 | 40 | A table named rental_data containing the dataset should exist in the restored SQL Server database. 41 | You can verify this by querying the table in SSMS. 42 | 43 | 44 | ```SQL 45 | USE tutorialdb; 46 | SELECT * FROM [dbo].[rental_data]; 47 | ``` 48 | 49 | >You now have the database and the data to use for training the model. 50 | 51 | ## Step 2.2 Explore the data with Python 52 | 53 | Loading data from SQL Server to Python is easy. So let's try it out. 54 | 55 | Open a new Python script in your IDE and run the following script. 56 | Just don't forget to replace "MYSQLSERVER" with the name of your database instance. 57 | 58 | ```python 59 | import pandas as pd 60 | from sklearn.linear_model import LinearRegression 61 | from sklearn.metrics import mean_squared_error 62 | 63 | #If you are running SQL Server 2017 RC1 and above: 64 | from revoscalepy import RxComputeContext, RxInSqlServer, RxSqlServerData 65 | from revoscalepy import rx_import 66 | 67 | #Connection string to connect to SQL Server named instance 68 | conn_str = 'Driver=SQL Server;Server=MYSQLSERVER;Database=TutorialDB;Trusted_Connection=True;' 69 | 70 | #Define the columns we wish to import 71 | column_info = { 72 | "Year" : { "type" : "integer" }, 73 | "Month" : { "type" : "integer" }, 74 | "Day" : { "type" : "integer" }, 75 | "RentalCount" : { "type" : "integer" }, 76 | "WeekDay" : { 77 | "type" : "factor", 78 | "levels" : ["1", "2", "3", "4", "5", "6", "7"] 79 | }, 80 | "Holiday" : { 81 | "type" : "factor", 82 | "levels" : ["1", "0"] 83 | }, 84 | "Snow" : { 85 | "type" : "factor", 86 | "levels" : ["1", "0"] 87 | } 88 | } 89 | 90 | #Get the data from SQL Server Table 91 | data_source = RxSqlServerData(table="dbo.rental_data", 92 | connection_string=conn_str, column_info=column_info) 93 | computeContext = RxInSqlServer( 94 | connection_string = conn_str, 95 | num_tasks = 1, 96 | auto_cleanup = False 97 | ) 98 | 99 | 100 | RxInSqlServer(connection_string=conn_str, num_tasks=1, auto_cleanup=False) 101 | 102 | # import data source and convert to pandas dataframe 103 | df = pd.DataFrame(rx_import(input_data = data_source)) 104 | print("Data frame:", df) 105 | # Get all the columns from the dataframe. 106 | columns = df.columns.tolist() 107 | # Filter the columns to remove ones we don't want to use in the training 108 | columns = [c for c in columns if c not in ["Year"]] 109 | ``` 110 | 111 | ```results 112 | Rows Processed: 453 113 | Data frame: Day Holiday Month RentalCount Snow WeekDay Year 114 | 0 20 1 1 445 2 2 2014 115 | 1 13 2 2 40 2 5 2014 116 | 2 10 2 3 456 2 1 2013 117 | 3 31 2 3 38 2 2 2014 118 | 4 24 2 4 23 2 5 2014 119 | 5 11 2 2 42 2 4 2015 120 | 6 28 2 4 310 2 1 2013 121 | ... 122 | [453 rows x 7 columns] 123 | ``` 124 | 125 | >You have now read the data from SQL Server to Python and explored it. 126 | 127 | ## Step 2.3 Train a model 128 | In order to predict, we first have to find a function (model) that best describes the dependency between the variables in our dataset. This step is called **training the model**. The training dataset will be a subset of the entire dataset. 129 | 130 | We are going to create a model using a linear regression algorithm. 131 | 132 | ```python 133 | # Store the variable we'll be predicting on. 134 | target = "RentalCount" 135 | # Generate the training set. Set random_state to be able to replicate results. 136 | train = df.sample(frac=0.8, random_state=1) 137 | # Select anything not in the training set and put it in the testing set. 138 | test = df.loc[~df.index.isin(train.index)] 139 | # Print the shapes of both sets. 140 | print("Training set shape:", train.shape) 141 | print("Testing set shape:", test.shape) 142 | # Initialize the model class. 143 | lin_model = LinearRegression() 144 | # Fit the model to the training data. 145 | lin_model.fit(train[columns], train[target]) 146 | ``` 147 | 148 | ```results 149 | Training set shape: (362, 7) 150 | Testing set shape: (91, 7) 151 | ``` 152 | 153 | >Now we have trained a linear regression model in Python! Let's use it to predict the rental count. 154 | 155 | ## Step 2.4 Prediction 156 | We are now going to use a predict function to predict the Rental Counts using our two models. 157 | 158 | ```python 159 | # Generate our predictions for the test set. 160 | lin_predictions = lin_model.predict(test[columns]) 161 | print("Predictions:", lin_predictions) 162 | # Compute error between our test predictions and the actual values. 163 | lin_mse = mean_squared_error(lin_predictions, test[target]) 164 | print("Computed error:", lin_mse) 165 | ``` 166 | 167 | ```results 168 | Predictions: [ 40. 38. 240. 39. 514. 48. 297. 25. 507. 24. 30. 54. 169 | 40. 26. 30. 34. 42. 390. 336. 37. 22. 35. 55. 350. 170 | 252. 370. 499. 48. 37. 494. 46. 25. 312. 390. 35. 35. 171 | 421. 39. 176. 21. 33. 452. 34. 28. 37. 260. 49. 577. 172 | 312. 24. 24. 390. 34. 64. 26. 32. 33. 358. 348. 25. 173 | 35. 48. 39. 44. 58. 24. 350. 651. 38. 468. 26. 42. 174 | 310. 709. 155. 26. 648. 617. 26. 846. 729. 44. 432. 25. 175 | 39. 28. 325. 46. 36. 50. 63.] 176 | Computed error: 3.59831533436e-26 177 | ``` 178 | 179 | > Congrats you just created a model with Python! Let us now deploy our Python code by moving it to SQL Server. 180 | -------------------------------------------------------------------------------- /pages/python/rentalprediction/step-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-steps 3 | language: Python 4 | title: Build a predictive model 5 | permalink: /python/rentalprediction/step/3 6 | --- 7 | 8 | 9 | >In this section, we will move the Python code we just wrote to SQL Server and deploy our predictive model with the help of SQL Server Machine Learning Services. 10 | >To deploy a model, you store the model in a hosting environment (like a database) and implement a prediction function that uses the model to predict. That function can be called from applications. 11 | 12 | SQL Server ML Services enables you to train and test predictive models in the context of SQL Server. You author T-SQL programs that contain embedded Python scripts, and the SQL Server database engine takes care of the execution. Because it executes in SQL Server, your models can easily be trained against data stored in the database. 13 | To deploy, you store your model in the database and create a stored procedure that predicts using the model. 14 | 15 | 16 | ## Step 3.1 Create a table for storing the model 17 | 18 | In SSMS, launch a new query window and run the following T-SQL script: 19 | 20 | ```sql 21 | USE TutorialDB; 22 | DROP TABLE IF EXISTS rental_py_models; 23 | GO 24 | CREATE TABLE rental_py_models ( 25 | model_name VARCHAR(30) NOT NULL DEFAULT('default model') PRIMARY KEY, 26 | model VARBINARY(MAX) NOT NULL 27 | ); 28 | GO 29 | ``` 30 | >You now have a table where the model can be saved. 31 | 32 | ## Step 3.2 Create stored procedure for generating the model 33 | 34 | We are now going to create a stored procedure in SQL Server to use the Python code we wrote in the previous module and generate the linear regression model inside the database. 35 | The Python code will be embedded in the TSQL statement. 36 | 37 | Now create the stored procedure to train/generate the model 38 | 39 | ```sql 40 | -- Stored procedure that trains and generates a Python model using the rental_data and a decision tree algorithm 41 | DROP PROCEDURE IF EXISTS generate_rental_py_model; 42 | go 43 | CREATE PROCEDURE generate_rental_py_model (@trained_model varbinary(max) OUTPUT) 44 | AS 45 | BEGIN 46 | EXECUTE sp_execute_external_script 47 | @language = N'Python' 48 | , @script = N' 49 | from sklearn.linear_model import LinearRegression 50 | import pickle 51 | 52 | df = rental_train_data 53 | 54 | # Get all the columns from the dataframe. 55 | columns = df.columns.tolist() 56 | 57 | # Store the variable well be predicting on. 58 | target = "RentalCount" 59 | 60 | 61 | 62 | # Initialize the model class. 63 | lin_model = LinearRegression() 64 | 65 | # Fit the model to the training data. 66 | lin_model.fit(df[columns], df[target]) 67 | 68 | #Before saving the model to the DB table, we need to convert it to a binary object 69 | trained_model = pickle.dumps(lin_model)' 70 | 71 | , @input_data_1 = N'select "RentalCount", "Year", "Month", "Day", "WeekDay", "Snow", "Holiday" from dbo.rental_data where Year < 2015' 72 | , @input_data_1_name = N'rental_train_data' 73 | , @params = N'@trained_model varbinary(max) OUTPUT' 74 | , @trained_model = @trained_model OUTPUT; 75 | END; 76 | GO 77 | 78 | --STEP 3 - Save model to table 79 | TRUNCATE TABLE rental_py_models; 80 | 81 | DECLARE @model VARBINARY(MAX); 82 | EXEC generate_rental_py_model @model OUTPUT; 83 | 84 | INSERT INTO rental_py_models (model_name, model) VALUES('linear_model', @model); 85 | 86 | ``` 87 | 88 | >The model is now saved in the database as a binary object. 89 | 90 | ## Step 3.3 Create stored procedure for prediction 91 | 92 | We are now very close to deploying our predicting model so that we can consume it from our applications. 93 | This last step includes creating a stored procedure that uses our model to predict the rental count. 94 | 95 | 1. Create a stored procedure that predicts using our model 96 | 97 | ```sql 98 | DROP PROCEDURE IF EXISTS py_predict_rentalcount; 99 | GO 100 | CREATE PROCEDURE py_predict_rentalcount (@model varchar(100)) 101 | AS 102 | BEGIN 103 | DECLARE @py_model varbinary(max) = (select model from rental_py_models where model_name = @model); 104 | 105 | EXEC sp_execute_external_script 106 | @language = N'Python', 107 | @script = N' 108 | 109 | # Import the scikit-learn function to compute error. 110 | from sklearn.metrics import mean_squared_error 111 | import pickle 112 | import pandas as pd 113 | 114 | rental_model = pickle.loads(py_model) 115 | 116 | df = rental_score_data 117 | 118 | # Get all the columns from the dataframe. 119 | columns = df.columns.tolist() 120 | 121 | # variable we will be predicting on. 122 | target = "RentalCount" 123 | 124 | # Generate our predictions for the test set. 125 | lin_predictions = rental_model.predict(df[columns]) 126 | print(lin_predictions) 127 | 128 | # Compute error between our test predictions and the actual values. 129 | lin_mse = mean_squared_error(lin_predictions, df[target]) 130 | #print(lin_mse) 131 | 132 | predictions_df = pd.DataFrame(lin_predictions) 133 | 134 | OutputDataSet = pd.concat([predictions_df, df["RentalCount"], df["Month"], df["Day"], df["WeekDay"], df["Snow"], df["Holiday"], df["Year"]], axis=1) 135 | ' 136 | , @input_data_1 = N'Select "RentalCount", "Year" ,"Month", "Day", "WeekDay", "Snow", "Holiday" from rental_data where Year = 2015' 137 | , @input_data_1_name = N'rental_score_data' 138 | , @params = N'@py_model varbinary(max)' 139 | , @py_model = @py_model 140 | with result sets (("RentalCount_Predicted" float, "RentalCount" float, "Month" float,"Day" float,"WeekDay" float,"Snow" float,"Holiday" float, "Year" float)); 141 | 142 | END; 143 | GO 144 | ``` 145 | 2. Create a table for storing the predictions 146 | ```sql 147 | DROP TABLE IF EXISTS [dbo].[py_rental_predictions]; 148 | GO 149 | --Create a table to store the predictions in 150 | CREATE TABLE [dbo].[py_rental_predictions]( 151 | [RentalCount_Predicted] [int] NULL, 152 | [RentalCount_Actual] [int] NULL, 153 | [Month] [int] NULL, 154 | [Day] [int] NULL, 155 | [WeekDay] [int] NULL, 156 | [Snow] [int] NULL, 157 | [Holiday] [int] NULL, 158 | [Year] [int] NULL 159 | ) ON [PRIMARY] 160 | GO 161 | ``` 162 | 163 | 3. Execute the stored procedure to predict rental counts 164 | 165 | ```sql 166 | TRUNCATE TABLE py_rental_predictions; 167 | --Insert the results of the predictions for test set into a table 168 | INSERT INTO py_rental_predictions 169 | EXEC py_predict_rentalcount 'linear_model'; 170 | 171 | -- Select contents of the table 172 | SELECT * FROM py_rental_predictions; 173 | ``` 174 | ## Step 3.4 Predict using native scoring (New!) 175 | In SQL Server 2017, we are introducing a native predict function in TSQL. The native PREDICT function allows you to perform faster scoring using certain RevoScaleR or revoscalepy models using a SQL query without invoking the R or Python runtime. The following code sample shows how you can train a model in Python using revoscalepy "Rx" functions, save the model to a table in the DB and predict using [native scoring](https://docs.microsoft.com/en-us/sql/advanced-analytics/sql-native-scoring). 176 | 177 | ```sql 178 | USE TutorialDB; 179 | 180 | --STEP 1 - Setup model table for storing the model 181 | DROP TABLE IF EXISTS rental_models; 182 | GO 183 | CREATE TABLE rental_models ( 184 | model_name VARCHAR(30) NOT NULL DEFAULT('default model'), 185 | lang VARCHAR(30), 186 | model VARBINARY(MAX), 187 | native_model VARBINARY(MAX), 188 | PRIMARY KEY (model_name, lang) 189 | 190 | ); 191 | GO 192 | 193 | --STEP 2 - Train model using revoscalepy rx_dtree or rxlinmod 194 | DROP PROCEDURE IF EXISTS generate_rental_py_native_model; 195 | go 196 | CREATE PROCEDURE generate_rental_py_native_model (@model_type varchar(30), @trained_model varbinary(max) OUTPUT) 197 | AS 198 | BEGIN 199 | EXECUTE sp_execute_external_script 200 | @language = N'Python' 201 | , @script = N' 202 | from revoscalepy import rx_lin_mod, rx_serialize_model, rx_dtree 203 | from pandas import Categorical 204 | import pickle 205 | 206 | rental_train_data["Holiday"] = rental_train_data["Holiday"].astype("category") 207 | rental_train_data["Snow"] = rental_train_data["Snow"].astype("category") 208 | rental_train_data["WeekDay"] = rental_train_data["WeekDay"].astype("category") 209 | 210 | if model_type == "linear": 211 | linmod_model = rx_lin_mod("RentalCount ~ Month + Day + WeekDay + Snow + Holiday", data = rental_train_data) 212 | trained_model = rx_serialize_model(linmod_model, realtime_scoring_only = True); 213 | if model_type == "dtree": 214 | dtree_model = rx_dtree("RentalCount ~ Month + Day + WeekDay + Snow + Holiday", data = rental_train_data) 215 | trained_model = rx_serialize_model(dtree_model, realtime_scoring_only = True); 216 | ' 217 | 218 | , @input_data_1 = N'select "RentalCount", "Year", "Month", "Day", "WeekDay", "Snow", "Holiday" from dbo.rental_data where Year < 2015' 219 | , @input_data_1_name = N'rental_train_data' 220 | , @params = N'@trained_model varbinary(max) OUTPUT, @model_type varchar(30)' 221 | , @model_type = @model_type 222 | , @trained_model = @trained_model OUTPUT; 223 | END; 224 | GO 225 | 226 | --STEP 3 - Save model to table 227 | 228 | --Line of code to empty table with models 229 | --TRUNCATE TABLE rental_models; 230 | 231 | --Save Linear model to table 232 | DECLARE @model VARBINARY(MAX); 233 | EXEC generate_rental_py_native_model "linear", @model OUTPUT; 234 | INSERT INTO rental_models (model_name, native_model, lang) VALUES('linear_model', @model, 'Python'); 235 | 236 | --Save DTree model to table 237 | DECLARE @model2 VARBINARY(MAX); 238 | EXEC generate_rental_py_native_model "dtree", @model2 OUTPUT; 239 | INSERT INTO rental_models (model_name, native_model, lang) VALUES('dtree_model', @model2, 'Python'); 240 | 241 | -- Look at the models in the table 242 | SELECT * FROM rental_models; 243 | 244 | GO 245 | 246 | --STEP 4 - Use the native PREDICT (native scoring) to predict number of rentals for both models 247 | DECLARE @model VARBINARY(MAX) = (SELECT TOP(1) native_model FROM dbo.rental_models WHERE model_name = 'linear_model' AND lang = 'Python'); 248 | SELECT d.*, p.* FROM PREDICT(MODEL = @model, DATA = dbo.rental_data AS d) WITH(RentalCount_Pred float) AS p; 249 | GO 250 | 251 | --Native scoring with dtree model 252 | DECLARE @model VARBINARY(MAX) = (SELECT TOP(1) native_model FROM dbo.rental_models WHERE model_name = 'dtree_model' AND lang = 'Python'); 253 | SELECT d.*, p.* FROM PREDICT(MODEL = @model, DATA = dbo.rental_data AS d) WITH(RentalCount_Pred float) AS p; 254 | GO 255 | 256 | ``` 257 | 258 | > Congrats, you just deployed a predictive model in SQL Server using Python! 259 | --------------------------------------------------------------------------------