【问题标题】:GROUP BY in CROSS APPLYGROUP BY 交叉应用
【发布时间】:2019-09-01 18:41:57
【问题描述】:

让我们有两张桌子

create table A (
  fkb int,
  groupby int
);

create table B (
  id int,
  search int
);

insert into A values (1, 1);
insert into B values (1, 1);
insert into B values (2, 1);

然后是下面的查询

select B.id, t.max_groupby - B.search diff
from B
cross apply ( 
  select max(A.groupby) max_groupby
  from A 
  where A.fkb = B.id 
) t

返回预期结果如下

id  diff
---------
1   0
2   NULL

但是,当我将group by A.fkb 添加到交叉应用中时,对应的A.fkb 不存在的B 行消失了。

select B.id, t.max_groupby - B.search diff
from B
cross apply ( 
  select max(A.groupby) max_groupby
  from A 
  where A.fkb = B.id 
  group by A.fkb
) t

我在 SQL Server 和 PostgreSQL 上进行测试(使用 cross join lateral 而不是 cross apply)。为什么group by 使该行消失?似乎cross apply 在第一种情况下表现为外连接,在后一种情况下表现为内连接。但是,我不清楚为什么。

【问题讨论】:

  • select B.id, (select max(A.groupby) from A where A.fkb = B.id) - B.search diff from B 我想你期待这个查询的结果。

标签: sql sql-server postgresql lateral-join


【解决方案1】:

这是因为:

  • A.fkb = 2GROUP BY 不返回任何内容
  • 没有 GROUP BY 返回 NULL

所以您的查询 CROSS APPLY 返回不同的结果。

select B.id, t.max_groupby - B.search diff
from B
outer apply ( 
  select max(A.groupby) max_groupby
  from A 
  where A.fkb = B.id 
  group by A.fkb
) t

输出:

id  diff
1   0
2   NULL

【讨论】:

  • 感谢您的回答。我的问题是:为什么cross apply 中的group by 会对结果产生影响?换句话说,为什么引入group by 会改变连接的语义?
【解决方案2】:

单独查看内部查询的结果可以看到:

select max(A.groupby) max_groupby
from A 
where A.fkb = 2;

返回一行,max_groupby = null:

max_groupby
-----------
     (null)

但是,由于没有 A.fkb = 2 分组的行,它会产生一个空结果,您可以在运行时看到:

select max(A.groupby) max_groupby
from A 
where A.fkb = 2
group by A.fkb

因此交叉连接不会返回 fkb = 2 的返回行

您需要使用外连接来包含来自B 的行。

在 Postgres 中你必须这样写:

select B.id, t.max_groupby - B.search diff
from B
  left join lateral ( 
    select max(A.groupby) max_groupby
    from A 
    where A.fkb = B.id 
    group by A.fkb
  ) t on true

我不知道在 SQL Server 中 left join lateral 的等效项是什么。
on true 需要写成 on 1=1

【讨论】:

  • 很好的答案,谢谢! SQL Server 中的左连接横向等效为outer apply
猜你喜欢
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多