从 R 执行时 SQL Server 查询失败

Roo*_*atu 6 sql-server r rodbc

我有以下简单的 SQL 服务器代码:

set nocount on;
if OBJECT_ID('tempdb..#A') IS NOT NULL DROP TABLE #A;

set nocount on;
create table #A
( obj_id int,
  obj_name varchar(50),
  obj_dt   datetime);

  insert into #A (
  obj_id,
  obj_name,
  obj_dt)
  values
  ( 1
   ,'name'
   ,'2019-01-01 00:00:00'
  ),
  ( 2
   ,NULL
   ,NULL
  ),
  ( 2
   ,'alias'
   ,'2019-02-01 00:00:00'
  );

set nocount on;
if OBJECT_ID('tempdb..#B') IS NOT NULL DROP TABLE #B;

set nocount on;
select 
 #A.obj_id
,subq.obj_name
,subq.obj_dt
into #B 
from #A
join (select
        obj_id,
        max(obj_name) as obj_name,
        max(obj_dt) as obj_dt
      from #A
      group by obj_id) as subq
on #A.obj_id = subq.obj_id;

set nocount on;
select * from #B;
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,在 Microsoft SQL Server Management Studio 中执行时返回以下数据:

obj_id  obj_name    obj_dt
1       name        2019-01-01 00:00:00.000
2       alias       2019-02-01 00:00:00.000
2       alias       2019-02-01 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好。现在我希望从 R 运行此代码并将相同的输出返回到 R。我将上面的查询存储在字符串中,将query我的RODBC连接存储在变量中connection,并尝试使用以下命令检索数据

sqlQuery(connection,query)
Run Code Online (Sandbox Code Playgroud)

结果是character(0)但是,如果我通过注释掉定义中的subq.obj_name和字段来修改上面的查询,那么代码会成功返回预期的数据集subq.obj_dt#B

obj_id
1      1
2      2
3      2
Run Code Online (Sandbox Code Playgroud)

来自 R。

那么这是怎么回事呢?两个 sql 查询都是有效的,并且在 Microsoft SQL Server 环境中成功运行,但只有一个在通过 R 进行管道传输时有效。我无法弄清楚 RODBC 代码无法处理第二个查询的原因。

Roo*_*atu 0

好的,所以我想我已经弄清楚这里出了什么问题。子查询

select
    obj_id,
    max(obj_name) as obj_name,
    max(obj_dt) as obj_dt
    from #A
group by obj_id
Run Code Online (Sandbox Code Playgroud)

产生隐藏警告。如果您只是按原样运行代码,则不会看到警告,但如果将输出存储在临时表中,则会生成警告消息:

select
    obj_id,
    max(obj_name) as obj_name,
    max(obj_dt) as obj_dt
    into #C
    from #A
group by obj_id
Run Code Online (Sandbox Code Playgroud)

警告:空值会被聚合或其他 SET 操作消除。

当它作为问题中原始 SQL 代码中的子查询的一部分运行时,警告将被隐藏。我相信这条消息在某种程度上是 R “看到”的输出的一部分,一旦 R 看到该输出,它就会终止查询。但由于尚未返回结果,R 中的输出为空(即character(0))。

为了解决这个问题,我将正在计算最大值的变量合并到一些最小值(我不确定 sql server 排序规则中的最小字符是什么,但'0'适合我的目的)。这个想法是在聚合之前删除NULL值,这样就不会生成警告。最终的工作SQL代码如下:

set nocount on;
if OBJECT_ID('tempdb..#A') IS NOT NULL DROP TABLE #A;

set nocount on;
create table #A
( obj_id int,
  obj_name varchar(50),
  obj_dt   datetime);

  insert into #A (
  obj_id,
  obj_name,
  obj_dt)
  values
  ( 1
   ,'name'
   ,'2019-01-01 00:00:00'
  ),
  ( 2
   ,NULL
   ,NULL
  ),
  ( 2
   ,'alias'
   ,'2019-02-01 00:00:00'
  );

set nocount on;
if OBJECT_ID('tempdb..#B') IS NOT NULL DROP TABLE #B;

set nocount on;
select 
 #A.obj_id
,subq.obj_name
,subq.obj_dt
into #B 
from #A
join
(select
        obj_id,
        max(isnull(obj_name,'0')) as obj_name,
        max(isnull(obj_dt,cast(-1 as datetime))) as obj_dt
      from #A
      group by obj_id) as subq 
on #A.obj_id = subq.obj_id;

set nocount on;
select * from #B; 
Run Code Online (Sandbox Code Playgroud)

我认为这种行为应该在 RODBC 包中得到解决,因为它很可能会导致其他问题,并且追踪根本原因和排除故障可能会有点棘手。