【问题标题】:Integrate R script into SELECT query将 R 脚本集成到 SELECT 查询中
【发布时间】:2018-02-08 05:04:18
【问题描述】:

所以我有以下集成的 R 代码,我使用它能够通过正则表达式匹配内容而没有太多复杂性(我最终想要做的比这个例子更复杂,所以非常需要正则表达式,这只是第一步):

DECLARE @in_adcn nvarchar(500)
DECLARE @out_ou nvarchar(500)
SET @in_adcn = N'CN=Surname\, Firstname (asdf),OU=999,OU=Department2,OU=Fixed,OU=Fixed,DC=Fixed,DC=Fixed,DC=Fixed'
SET @out_ou = N''

-- Extract department name from AD OU string
EXEC sp_execute_external_script @language=N'R',
    @script = N'
        pat = "^.+OU=([^,]+),OU=Fixed,OU=Fixed,DC=Fixed,DC=Fixed,DC=Fixed$";
        m <- gsub(pat, "\\1", regmatches(in_adcn1, gregexpr(pat, in_adcn1))[[1]]);
        out_ou1 <- m;',
    @params = N'@in_adcn1 varchar(500), @out_ou1 varchar(500) output',
    @in_adcn1 = @in_adcn,
    @out_ou1 = @out_ou OUTPUT
WITH RESULT SETS NONE;
SELECT @out_ou;
GO

这很好用,它从 AD distinctName 字符串返回我想要的内容(在本例中:“Department2”)。

现在我想要这个 SELECT 查询中的输出字符串(R 脚本的输入字符串是 acad.ADCn):

SELECT
    acad.ADCn,
    (
        --<here should be the code that returns the string from the R script above>
    ) AS Departmentname,
    acad.NBAccountName,
    acb.eMail
FROM
    MyDB.dbo.AccountTable AS acad
LEFT JOIN
    MyDB.dbo.AddressTable AS acb
    ON
        acad.[ObjectID]
        = acb.[ObjectID]

到目前为止,我还没有设法做到这一点。任何帮助将不胜感激。

【问题讨论】:

  • 您希望有一个标量用户定义函数调用sp_execute_external_script,您将acad.ADcn 传递给函数。但是,由于您不能从函数内部调用 UDF,因此您很不走运。但是,在这种情况下 - 为什么要将 R 用于正则表达式,您不能创建一个 SQLCLR 过程/函数来为您执行此操作吗?

标签: sql-server r tsql sql-server-2016


【解决方案1】:

考虑将整个SELECT 查询输入为@input_data_1 参数(遵循tutorial 示例)。然后,对新保存的数据框列 DepartmentName 运行正则表达式操作。最后,输出整个四列结果集。

EXECUTE sp_execute_external_script
      @language = N'R'
    , @script = N' df <- InputDataSet;
                   pat = "^.+OU=([^,]+),OU=Fixed,OU=Fixed,DC=Fixed,DC=Fixed,DC=Fixed$";
                   df$DepartmentName <- gsub(pat, "\\1", regmatches(df$ADCn, gregexpr(pat, df$ADCn))[[1]]);
                   OutputDataSet <- df[c("ADCn", "DepartmentName", "NBAccountName", "eMail")];'
    , @input_data_1 = N' SELECT acad.ADCn, acad.NBAccountName, acb.eMail
                         FROM MyDB.dbo.AccountTable AS acad
                         LEFT JOIN MyDB.dbo.AddressTable AS acb
                            ON acad.[ObjectID] = acb.[ObjectID];'
    WITH RESULT SETS (( [ADCn] varchar(255), [DepartmentName] varchar(255), [NBAccountName] varchar(255), [eMail] varchar(255) ));

当然没有数据,以上是未经测试的。请根据需要进行调整,尤其是 ADCn 的输入。

【讨论】:

  • 几乎完美!只剩下 2 个问题:不知何故,这会为每个 ADCn 返回相同的部门名称(应该有很多不同的部门名称)。包含“Department9”的第一个 ADCn 似乎是一次又一次使用的那个,因为最终它们都在“Department9”中(这是不正确的)。第二个问题:这会在消息输出中生成一个“文本表”。这不应该返回一个“真实”的表,因为这就是我需要的。谢谢!
  • 这不是因为[1]这行代码:df$DepartmentName &lt;- gsub(pat, "\\1", regmatches(df$ADCn, gregexpr(pat, df$ADCn))[[1]]);吗? “真正的桌子”是什么意思?当我运行类似的代码时,我会得到一个带有列等的结果集。
  • 好的,谢谢。不用管桌子的问题,我只是有一个不同的显示处于活动状态。它现在按预期工作。谢谢大家。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-14
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多