mirror of
https://github.com/Microsoft/sql-server-samples.git
synced 2025-12-08 14:58:54 +00:00
getting started samples for Rservices added
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
|
||||
# Input Query
|
||||
input_query <- "
|
||||
SELECT
|
||||
ss_customer_sk AS customer,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
round(CASE WHEN ( returns_count IS NULL ) THEN 0.0 ELSE returns_count END, 0) AS frequency
|
||||
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
ss_customer_sk,
|
||||
-- return order ratio
|
||||
COUNT(distinct(ss_ticket_number)) AS orders_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(ss_item_sk) AS orders_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( ss_net_paid ) AS orders_money
|
||||
FROM store_sales s
|
||||
GROUP BY ss_customer_sk
|
||||
) orders
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
sr_customer_sk,
|
||||
-- return order ratio
|
||||
count(distinct(sr_ticket_number)) as returns_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(sr_item_sk) as returns_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( sr_return_amt ) AS returns_money
|
||||
FROM store_returns
|
||||
GROUP BY sr_customer_sk
|
||||
) returned ON ss_customer_sk=sr_customer_sk
|
||||
"
|
||||
|
||||
# Define the connection string
|
||||
connStr <- paste("Driver=SQL Server;Server=", "NELLIELAPTOP", ";Database=", "tpcx1b", ";Trusted_Connection=true;", sep = "");
|
||||
|
||||
# Input customer data that needs to be classified
|
||||
customer_returns <- RxSqlServerData(sqlQuery = input_query,
|
||||
colClasses = c(customer = "numeric", orderRatio = "numeric", itemsRatio = "numeric", monetaryRatio = "numeric", frequency = "numeric"),
|
||||
connectionString = connStr);
|
||||
|
||||
|
||||
# Transform the data from an input dataset to an output dataset
|
||||
customer_data <- rxDataStep(customer_returns);
|
||||
#Look at the data we just loaded from SQL Server
|
||||
head(customer_data, n = 5);
|
||||
|
||||
# Determine number of clusters
|
||||
#Using a plot of the within groups sum of squares by number of clusters extracted can help determine the appropriate number of clusters.
|
||||
#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
|
||||
wss <- (nrow(customer_data) - 1) * sum(apply(customer_data, 2, var))
|
||||
for (i in 2:20) {
|
||||
xt = kmeans(customer_data, centers = i)
|
||||
print(xt$ifault)
|
||||
wss[i] <- sum(kms = kmeans(customer_data, centers = i)$withinss)
|
||||
}
|
||||
plot(1:20, wss, type = "b", xlab = "Number of Clusters", ylab = "Within groups sum of squares")
|
||||
|
||||
# Output table to hold the customer group mappings
|
||||
return_cluster = RxSqlServerData(table = "return_cluster", connectionString = connStr);
|
||||
|
||||
# Set.seed for random number generator for predicatability
|
||||
set.seed(10);
|
||||
|
||||
# Generate clusters using rxKmeans and output key / cluster to a table in SQL Server called return_cluster
|
||||
clust <- rxKmeans( ~ orderRatio + itemsRatio + monetaryRatio + frequency, customer_returns, numClusters = 4
|
||||
, outFile = return_cluster, outColName = "cluster", extraVarsToWrite = c("customer"), overwrite = TRUE);
|
||||
|
||||
# Read the custome returns cluster table
|
||||
customer_cluster <- rxDataStep(return_cluster);
|
||||
|
||||
#Plot the clusters (need to install library "cluster")
|
||||
#install.packages("cluster")
|
||||
library("cluster");
|
||||
clusplot(customer_data, customer_cluster$cluster, color=TRUE, shade=TRUE, labels=4, lines=0, plotchar = TRUE);
|
||||
|
||||
#Look at the clustering details and analyze results
|
||||
clust
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
USE [tpcx1b]
|
||||
|
||||
DROP PROC IF EXISTS generate_customer_return_clusters;
|
||||
GO
|
||||
CREATE procedure [dbo].[generate_customer_return_clusters]
|
||||
AS
|
||||
/*
|
||||
This procedure uses R to classify customers into different groups based on their
|
||||
purchase & return history.
|
||||
*/
|
||||
BEGIN
|
||||
DECLARE @duration FLOAT
|
||||
, @predict_duration FLOAT
|
||||
, @instance_name NVARCHAR(100) = @@SERVERNAME
|
||||
, @database_name NVARCHAR(128) = db_name()
|
||||
|
||||
-- Input query to generate the purchase history & return metrics
|
||||
, @input_query NVARCHAR(MAX) = N'
|
||||
SELECT
|
||||
ss_customer_sk AS customer,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
round(CASE WHEN ( returns_count IS NULL ) THEN 0.0 ELSE returns_count END, 0) AS frequency
|
||||
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
ss_customer_sk,
|
||||
-- return order ratio
|
||||
COUNT(distinct(ss_ticket_number)) AS orders_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(ss_item_sk) AS orders_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( ss_net_paid ) AS orders_money
|
||||
FROM store_sales s
|
||||
GROUP BY ss_customer_sk
|
||||
) orders
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
sr_customer_sk,
|
||||
-- return order ratio
|
||||
count(distinct(sr_ticket_number)) as returns_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(sr_item_sk) as returns_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( sr_return_amt ) AS returns_money
|
||||
FROM store_returns
|
||||
GROUP BY sr_customer_sk
|
||||
) returned ON ss_customer_sk=sr_customer_sk
|
||||
'
|
||||
|
||||
EXEC sp_execute_external_script
|
||||
@language = N'R'
|
||||
, @script = N'
|
||||
# Define the connection string
|
||||
connStr <- paste("Driver=SQL Server;Server=", instance_name, ";Database=", database_name, ";Trusted_Connection=true;", sep="");
|
||||
|
||||
|
||||
# Input customer data that needs to be classified. This is the result we get from our query
|
||||
customer_returns <- RxSqlServerData(sqlQuery = input_query,
|
||||
colClasses = c(customer = "numeric", orderRatio = "numeric", itemsRatio = "numeric", monetaryRatio = "numeric", frequency = "numeric"),
|
||||
connectionString = connStr);
|
||||
|
||||
# Output table to hold the customer cluster mappings
|
||||
return_cluster = RxSqlServerData(table = "customer_return_clusters", connectionString = connStr);
|
||||
|
||||
# set.seed for random number generator for predicatability
|
||||
set.seed(10);
|
||||
|
||||
# generate clusters using rxKmeans and output clusters to a table called "customer_return_clusters".
|
||||
clust <- rxKmeans( ~ orderRatio + itemsRatio + monetaryRatio + frequency, customer_returns, numClusters = 4
|
||||
, outFile = return_cluster, outColName = "cluster", writeModelVars = TRUE , extraVarsToWrite = c("customer"), overwrite = TRUE);
|
||||
'
|
||||
, @input_data_1 = N''
|
||||
, @params = N'@instance_name nvarchar(100), @database_name nvarchar(128), @input_query nvarchar(max), @duration float OUTPUT'
|
||||
, @instance_name = @instance_name
|
||||
, @database_name = @database_name
|
||||
, @input_query = @input_query
|
||||
, @duration = @duration OUTPUT;
|
||||
END;
|
||||
|
||||
GO
|
||||
|
||||
|
||||
--Empty table of the results before running the stored procedure
|
||||
TRUNCATE TABLE customer_return_clusters;
|
||||
|
||||
--Execute the clustering. This will load the table customer_return_clusters with cluster mappings
|
||||
EXEC [dbo].[generate_customer_return_clusters];
|
||||
|
||||
--Now select data from table customer_return_clusters to verify that the clustering data was loaded
|
||||
SELECT * FROM customer_return_clusters;
|
||||
|
||||
--Select email addresses of customers in cluster 1
|
||||
SELECT customer.[c_email_address], customer.c_customer_sk
|
||||
FROM dbo.customer
|
||||
JOIN
|
||||
[dbo].[customer_return_clusters] as r
|
||||
ON r.customer = customer.c_customer_sk
|
||||
WHERE r.cluster = 1
|
||||
@@ -0,0 +1,54 @@
|
||||
#Connection string to connect to SQL Server
|
||||
connStr <- paste("Driver=SQL Server; Server=", "MyServer",
|
||||
";Database=", "tutorialdb", ";Trusted_Connection=true;", sep = "");
|
||||
|
||||
#Get the data from SQL Server Table
|
||||
SQL_rentaldata <- RxSqlServerData(table = "dbo.rental_data",
|
||||
connectionString = connStr, returnDataFrame = TRUE);
|
||||
|
||||
#Import the data into a data frame
|
||||
rentaldata <- rxImport(SQL_rentaldata);
|
||||
|
||||
#Let's see the structure of the data and the top rows
|
||||
head(rentaldata);
|
||||
str(rentaldata);
|
||||
|
||||
#Changing the three factor columns to factor types
|
||||
#This helps when building the model because we are explicitly saying that these values are categorical
|
||||
rentaldata$Holiday <- factor(rentaldata$Holiday);
|
||||
rentaldata$Snow <- factor(rentaldata$Snow);
|
||||
rentaldata$WeekDay <- factor(rentaldata$WeekDay);
|
||||
|
||||
#Visualize the dataset after the change
|
||||
str(rentaldata);
|
||||
|
||||
#Now let's split the dataset into 2 different sets
|
||||
#One set for training the model and the other for validating it
|
||||
train_data = rentaldata[rentaldata$Year < 2015,];
|
||||
test_data = rentaldata[rentaldata$Year == 2015,];
|
||||
|
||||
#Use this column to check the quality of the prediction against actual values
|
||||
actual_counts <- test_data$RentalCount;
|
||||
|
||||
#Model 1: Use rxLinMod to create a linear regression model. We are training the data using the training data set
|
||||
model_linmod <- rxLinMod(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = train_data);
|
||||
|
||||
#Model 2: Use rxDTree to create a decision tree model. We are training the data using the training data set
|
||||
model_dtree <- rxDTree(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = train_data);
|
||||
|
||||
#Use the models we just created to predict using the test data set.
|
||||
#That enables us to compare actual values of RentalCount from the two models and compare to the actual values in the test data set
|
||||
predict_linmod <- rxPredict(model_linmod, test_data, writeModelVars = TRUE);
|
||||
|
||||
predict_dtree <- rxPredict(model_dtree, test_data, writeModelVars = TRUE);
|
||||
|
||||
#Look at the top rows of the two prediction data sets.
|
||||
head(predict_linmod);
|
||||
head(predict_dtree);
|
||||
|
||||
#Now we will use the plotting functionality in R to viusalize the results from the predictions
|
||||
#We are plotting the difference between actual and predicted values for both models to compare accuracy
|
||||
par(mfrow = c(2, 1));
|
||||
plot(predict_linmod$RentalCount_Pred - predict_linmod$RentalCount, main = "Difference between actual and predicted. rxLinmod");
|
||||
plot(predict_dtree$RentalCount_Pred - predict_dtree$RentalCount, main = "Difference between actual and predicted. rxDTree");
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
--Before we start, we need to restore the DB for this tutorial.
|
||||
--Step1:Download the compressed backup file
|
||||
--Save the file on a location where SQL Server can access it. For example:C:\Program Files \Microsoft SQL Server \MSSQL13.MSSQLSERVER\MSSQL\Backup\
|
||||
--In a new query window in SSMS, execute the following restore statement, but REMEMBER TO CHANGE THE FILE PATHS
|
||||
--to match the directories of your installation!
|
||||
USE master;
|
||||
GO
|
||||
RESTORE DATABASE TutorialDB
|
||||
FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\TutorialDB.bak'
|
||||
WITH
|
||||
MOVE 'TutorialDB' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\TutorialDB.mdf'
|
||||
, MOVE 'TutorialDB_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\TutorialDB.ldf';
|
||||
GO
|
||||
|
||||
USE tutorialdb;
|
||||
SELECT * FROM [dbo].[rental_data];
|
||||
|
||||
|
||||
-- Operationalize
|
||||
USE tutorialdb;
|
||||
GO
|
||||
-- Setup model table
|
||||
DROP TABLE IF EXISTS rental_rx_models;
|
||||
GO
|
||||
CREATE TABLE rental_rx_models (
|
||||
model_name VARCHAR(30) NOT NULL DEFAULT('default model') PRIMARY KEY,
|
||||
model VARBINARY(MAX) NOT NULL
|
||||
);
|
||||
GO
|
||||
|
||||
-- Stored procedure that trains and generates a model using the rental_data and a decision tree algorithm
|
||||
DROP PROCEDURE IF EXISTS generate_rental_rx_model;
|
||||
go
|
||||
CREATE PROCEDURE generate_rental_rx_model (@trained_model varbinary(max) OUTPUT)
|
||||
AS
|
||||
BEGIN
|
||||
EXECUTE sp_execute_external_script
|
||||
@language = N'R'
|
||||
, @script = N'
|
||||
require("RevoScaleR");
|
||||
|
||||
rental_train_data$Holiday = factor(rental_train_data$Holiday);
|
||||
rental_train_data$Snow = factor(rental_train_data$Snow);
|
||||
rental_train_data$WeekDay = factor(rental_train_data$WeekDay);
|
||||
|
||||
#Create a dtree model and train it using the training data set
|
||||
model_dtree <- rxDTree(RentalCount ~ Month + Day + WeekDay + Snow + Holiday, data = rental_train_data);
|
||||
#Before saving the model to the DB table, we need to serialize it
|
||||
trained_model <- as.raw(serialize(model_dtree, connection=NULL));'
|
||||
|
||||
, @input_data_1 = N'select "RentalCount", "Month", "Day", "WeekDay", "Snow", "Holiday" from dbo.rental_data where Year < 2015'
|
||||
, @input_data_1_name = N'rental_train_data'
|
||||
, @params = N'@trained_model varbinary(max) OUTPUT'
|
||||
, @trained_model = @trained_model OUTPUT;
|
||||
END;
|
||||
GO
|
||||
TRUNCATE TABLE rental_rx_models;
|
||||
--Script to call the stored procedure that generates the rxDTree model and save the model in a table in SQL Server
|
||||
DECLARE @model VARBINARY(MAX);
|
||||
EXEC generate_rental_rx_model @model OUTPUT;
|
||||
INSERT INTO rental_rx_models (model_name, model) VALUES('rxDTree', @model);
|
||||
SELECT * FROM rental_rx_models;
|
||||
GO
|
||||
|
||||
--Stored procedure that takes model name and new data as inout parameters and predicts the rental count for the new data
|
||||
DROP PROCEDURE IF EXISTS predict_rentals;
|
||||
GO
|
||||
CREATE PROCEDURE predict_rentals (@model VARCHAR(100),@q NVARCHAR(MAX))
|
||||
AS
|
||||
BEGIN
|
||||
DECLARE @rx_model VARBINARY(MAX) = (SELECT model FROM rental_rx_models WHERE model_name = @model);
|
||||
EXECUTE sp_execute_external_script
|
||||
@language = N'R'
|
||||
, @script = N'
|
||||
require("RevoScaleR");
|
||||
|
||||
#The InputDataSet contains the new data passed to this stored proc. We will use this data to predict.
|
||||
rentals = InputDataSet;
|
||||
|
||||
#Convert types to factors
|
||||
rentals$Holiday = factor(rentals$Holiday);
|
||||
rentals$Snow = factor(rentals$Snow);
|
||||
rentals$WeekDay = factor(rentals$WeekDay);
|
||||
|
||||
#Before using the model to predict, we need to unserialize it
|
||||
rental_model = unserialize(rx_model);
|
||||
|
||||
#Call prediction function
|
||||
rental_predictions = rxPredict(rental_model, rentals);'
|
||||
, @input_data_1 = @q
|
||||
, @output_data_1_name = N'rental_predictions'
|
||||
, @params = N'@rx_model varbinary(max)'
|
||||
, @rx_model = @rx_model
|
||||
WITH RESULT SETS (("RentalCount_Predicted" FLOAT));
|
||||
|
||||
END;
|
||||
GO
|
||||
|
||||
--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
|
||||
EXEC dbo.predict_rentals @model = 'rxDTree',
|
||||
@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';
|
||||
GO
|
||||
|
||||
Reference in New Issue
Block a user