Как вернуть имена столбцов и итоговые значения из хранимой процедуры SQL Server R? - PullRequest
0 голосов
/ 03 июня 2018

Я создал хранимую процедуру, в которой используется библиотека dplyr с целью группировки по StudyID и ProductNumber.Я хочу вернуть среднее значение каждого значения в полях c1-c8, а также стандартное отклонение для тех же полей.

Моя хранимая процедура выглядит следующим образом:

ALTER PROCEDURE [dbo].[spCodeMeans]
    @StudyID INT,
    @StudyID_outer INT OUT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @inquery NVARCHAR(MAX) = N'Select
        c.StudyID, c.RespID, c.ProductNumber, c.ProductSequence, c.BottomScaleValue, 
        c.BottomScaleAnchor, c.TopScaleValue, c.TopScaleAnchor, c.StudyDate,
        c.DayOfWeek, c.A, c.B, c.C, c.D, c.E, c.F,
        c.DependentVarYN, c.VariableAttributeID, c.VarAttributeName, c.[1] as c1, 
        c.[2] as c2, c.[3] as c3, c.[4] as c4, c.[5] as c5, c.[6] as c6, c.[7] as c7, c.[8] as c8
        from ClosedStudyResponses c
        --Sensory Value Attributes only for mean and standard deviation analytics.
        where VariableAttributeID = 1
        and c.StudyID = 22'
        ;

    BEGIN TRY
        EXEC sp_execute_external_script
                @language = N'R',
                @script = N'
        library(dplyr)
            OutputDataSet <- InputDataSet %>%
                group_by (StudyID, ProductNumber) %>%
                summarise(c1_mean = mean(c1), c2_mean = mean(c2), c3_mean = mean(c3), c4_mean = mean(c4), c5_mean = mean(c5), c6_mean = mean(c6), 
                c7_mean = mean(c7), c8_mean = mean(c8), c1_sd = sd(c1), c2_sd = sd(c2), c3_sd = sd(c3), c4_sd = sd(c4), c5_sd = sd(c5), c6_sd = sd(c6), 
                c7_sd = sd(c7), c8_sd = sd(c8)) %>%
            `colnames<-`(c("StudyID", "ProductNumber","c1_mean","c2_mean","c3_mean","c4_mean","c5_mean","c6_mean","c7_mean",
            "c8_mean","c1_sd","c2_sd","c3_sd","c4_sd","c5_sd","c6_sd","c7_sd","c8_sd"))',
                @input_data_1 = @inquery
    END TRY
    BEGIN CATCH
        THROW;
    END CATCH

Результаты не включают имена столбцов и не включают среднее значение и стандартное отклонение для полей с1 по с8.Как мне настроить мой синтаксис для достижения этой цели?

Обновление: согласно предложению я пересмотрел хранимую процедуру, чтобы вставить результаты во временную таблицу.Пересмотренный синтаксис выглядит следующим образом:

ALTER PROCEDURE [dbo].[spCodeMeans]
-- Add the parameters for the stored procedure here
@StudyID int,
@StudyID_outer int OUT


AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

--Create temptable to store the outputdataset
Create table #temp_table (
    StudyID int,
    ProductNumber int,
    c1_mean decimal,
    c2_mean decimal,
    c3_mean decimal,
    c4_mean decimal,
    c5_mean decimal,
    c6_mean decimal,
    c7_mean decimal,
    c8_mean decimal,

    c1_sd decimal,
    c2_sd decimal,
    c3_sd decimal,
    c4_sd decimal,
    c5_sd decimal,
    c6_sd decimal,
    c7_sd decimal,
    c8_sd decimal
);

-- Insert statements for procedure here
Declare @inquery nvarchar(max) = N'Select
        c.StudyID, c.RespID, c.ProductNumber, c.ProductSequence, c.BottomScaleValue, 
        c.BottomScaleAnchor, c.TopScaleValue, c.TopScaleAnchor, c.StudyDate,
        c.DayOfWeek, c.A, c.B, c.C, c.D, c.E, c.F,
        c.DependentVarYN, c.VariableAttributeID, c.VarAttributeName, c.[1] as c1, 
        c.[2] as c2, c.[3] as c3, c.[4] as c4, c.[5] as c5, c.[6] as c6, c.[7] as c7, c.[8] as c8
        from ClosedStudyResponses c
        --Sensory Value Attributes only for mean and standard deviation analytics.
        where VariableAttributeID = 1
        and c.StudyID = 22'
        ;
 BEGIN TRY
        Insert into #temp_table
        exec sp_execute_external_script
        @language = N'R',
        @script = N'
        library(dplyr)
            OutputDataSet <- InputDataSet %>%
                group_by (StudyID, ProductNumber) %>%
                summarise_all(.funs=c(mean, sd)) %>%
                setNames(c("StudyID","ProductNumber",
                paste0("c",1:8, "_mean"),
                paste0("c",1:8, "_sd")))
            ',
@input_data_1 = @inquery,
@output_data_1 = N'OutputDataSet';

END TRY

BEGIN CATCH
    THROW;
END CATCH

Select * from #temp_table;
END

Когда я пытаюсь запустить процедуру, я получаю сообщение об ошибке Procedure expects parameter '@params' of type 'ntext/nchar/nvarchar'. Обратите внимание, что я уже объявил @inquery как NVARCHAR (Макс).Есть еще один шаг, который я пропустил?

Обновление № 2: я потратил некоторое время на переработка хранимой процедуры и обнаружил, что вывод должен быть в формате data.frame.Я изменил часть R хранимой процедуры соответственно.Теперь отображаются имена моих столбцов, но данные, средние значения или стандартные отклонения не возвращаются.Текущая хранимая процедура выглядит следующим образом:

ALTER PROCEDURE [dbo].[spCodeMeans]
-- Add the parameters for the stored procedure here
@StudyID int

AS
BEGIN


-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;



-- Insert statements for procedure here
Declare @sStudy varchar(50)
Set @sStudy = Convert(Varchar(50),@StudyID)
Declare @inquery nvarchar(max) = N'Select
        c.StudyID, c.RespID, c.ProductNumber, c.ProductSequence, c.BottomScaleValue, 
        c.BottomScaleAnchor, c.TopScaleValue, c.TopScaleAnchor, c.StudyDate,
        c.DayOfWeek, c.A, c.B, c.C, c.D, c.E, c.F,
        c.DependentVarYN, c.VariableAttributeID, c.VarAttributeName, c.[1] as c1, 
        c.[2] as c2, c.[3] as c3, c.[4] as c4, c.[5] as c5, c.[6] as c6, c.[7] as c7, c.[8] as c8
        from ClosedStudyResponses c
        --Sensory Value Attributes only for mean and standard deviation analytics.
        where VariableAttributeID = 1
        and c.StudyID =' +@sStudy ;

BEGIN TRY
        --Insert into CodeMeans
        exec sp_execute_external_script
        @language = N'R',
        @script = N'
        library(dplyr)
        codemeans <- function(StudyID){
            res <- InputDataSet %>%
                group_by (StudyID, ProductNumber) %>%
                summarise_all(.funs=c(mean, sd)) %>%
                setNames(c("StudyID","ProductNumber",
                paste0("c",1:8, "_mean"),
                paste0("c",1:8, "_sd")))
            df <- data.frame(res)
            }
            ',
@input_data_1 = @inquery,
@output_data_1_name = N'df',
@params = N'@StudyID int',
@StudyID = @StudyID

END TRY

BEGIN CATCH
    THROW;
END CATCH

Select * from CodeMeans;
END

Итак, на данный момент я ищу руководство о том, как вернуть выходные данные из базового запроса, а также средние и стандартные отклонения.

1 Ответ

0 голосов
/ 03 июня 2018

В настоящее время вы не определяете выходной набор и не вставляете возврат в предопределенную таблицу.Рассмотрите следующую корректировку с использованием временной таблицы (при необходимости настройте типы ниже).Также рассмотрите возможность использования dplyr::summarise_all() для множественных вызовов агрегации, setNames для сохранения потока трубопровода и paste, чтобы избежать повторения в именах.

ALTER PROCEDURE [dbo].[spCodeMeans]
-- Add the parameters for the stored procedure here
@StudyID int,
@StudyID_outer int OUT

AS
BEGIN
   -- SET NOCOUNT ON added to prevent extra result sets from
   -- interfering with SELECT statements.
   SET NOCOUNT ON;


   CREATE TABLE #tmp_table -- LOCAL TEMP TABLE (EXISTS ONLY IN SESSION)
   (
        StudyID INTEGER,
        ProductNumber VARCHAR(50),
        c1_mean DECIMAL(10,2), c2_mean DECIMAL(10,2), c3_mean DECIMAL(10,2), c4_mean DECIMAL(10,2),
        c5_mean DECIMAL(10,2), c6_mean DECIMAL(10,2), c7_mean DECIMAL(10,2), c8_mean DECIMAL(10,2),
        c1_sd DECIMAL(10,2), c2_sd DECIMAL(10,2), c3_sd DECIMAL(10,2), c4_sd DECIMAL(10,2),
        c5_sd DECIMAL(10,2), c6_sd DECIMAL(10,2), c7_sd DECIMAL(10,2), c8_sd DECIMAL(10,2)
   );

   DECLARE @inquery nvarchar(max) = -- ...same as before...

   BEGIN TRY
        -- ACTION QUERY
        INSERT INTO @temp_table
        EXEC sp_execute_external_script
        @language = N'R',
        @script = N'
        library(dplyr)
          OutputDataSet <- InputDataSet %>%
            group_by (StudyID, ProductNumber) %>%
            summarise_all(.funs=c(mean, sd)) %>%
            setNames(c("StudyID", "ProductNumber", 
                       paste0("c", 1:8, "_mean"), 
                       paste0("c", 1:8, "_sd")))',
        @input_data_1 = @inquery,
        @output_data_1 = N'OutputDataSet';

   END TRY

   BEGIN CATCH
       THROW;
   END CATCH

   -- RESULTSET QUERY
   SELECT * FROM @temp_table;

END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...