SQL Server:交叉应用 - 为 NULL 结果记录 0

Posted

技术标签:

【中文标题】SQL Server:交叉应用 - 为 NULL 结果记录 0【英文标题】:SQL Server: Cross-apply - record 0 for NULL results 【发布时间】:2019-03-21 12:25:21 【问题描述】:

T1 是公司及其(多个用户)的表,T2 是注册用户的表。我计算了 T1 中的每家公司,有多少用户在 T2 中但需要 c3 出现在结果表中,#regUser == 0:

T1:

company         user
c1               u1
c1               u2
c2               u2
c2               u3
c3               u4
c3               u1

T2:

user
u2
u3

所以结果表应该如下所示:

company         #regUser
c1                 1
c2                 2
c3                 0

使用以下代码,我只能获得非空公司的结果:

select t1s.company, count(1)
from (select * from t1) t1s
  cross apply (select *
               from t2 t2s
               where t2s.reguser = t1s.[user]) t12s
group by t1s.company

谢谢

【问题讨论】:

这个查询过于复杂。例如,from (select * from t1) t1s 仅相当于 from t1。你为什么不在两个表之间尝试一个简单的左连接? 为什么用子查询来写?这可以简单地写成select t1s.company, count(1) from t1 t1s JOIN t2 t2s ON t2s.reguser = t1s.[user] group by t1s.company 【参考方案1】:

只使用左连接

   select t1.company,count(t2.user)
     from t1 left join t2 on t1.user=t2.user
group by t1.company

根据您的要求,子查询不是必需的

但是如果你想使用apply 那么你需要像下面这样的查询

select t1s.company, count(t12s.Users)
from (select * from t1) t1s
  outer apply (select Users
               from t2 t2s
               where t2s.Users = t1s.[Users]) t12s
group by t1s.company

输出

company     #regUser
c1          1
c2          2
c3          0

demolink

【讨论】:

【参考方案2】:

您可以使用LEFT JOIN 来获取左表的所有信息以及右表的匹配信息。通过使用GROUP BY,您可以按公司对行进行分组,并获取每个公司的注册用户COUNT

SELECT t1.company, COUNT(t2.[user]) AS regUser 
FROM t1 LEFT JOIN t2 ON t1.[user] = t2.[user]
GROUP BY t1.company
ORDER BY t1.company ASC

你也可以使用CROSS APPLY来解决这个问题:

SELECT t1.company, SUM(CASE WHEN t1.[user] = t2.[user] THEN 1 ELSE 0 END) AS regUser 
FROM t1 CROSS APPLY t2
GROUP BY t1.company
ORDER BY t1.company ASC

demo on dbfiddle.uk

【讨论】:

【参考方案3】:

你只需要一个左连接:

select company,count(t2.[user])
from t1 left outer join t2 on t1.[user]=t2.[user]
group by company

问题的查询过于复杂。例如,from (select * from t1) t1s 等价于 from t1 as t1s

【讨论】:

【参考方案4】:

只是LEFT JOINSUM()

CREATE TABLE T1(
  Company VARCHAR(20),
  Users VARCHAR(20)
);

CREATE TABLE T2(
  Users VARCHAR(20)
);

INSERT INTO T1 VALUES
('c1', 'u1'),
('c1', 'u2'),
('c2', 'u2'),
('c2', 'u3'),
('c3', 'u4'),
('c3', 'u1');

INSERT INTO T2 VALUES
('u2'),
('u3');

SELECT T1.Company,
       SUM(CASE WHEN T2.Users IS NULL THEN 0 ELSE 1 END) Cnt
FROM T1 LEFT JOIN T2
ON T1.Users = T2.Users
GROUP BY T1.Company;

返回:

+---------+-----+
| Company | Cnt |
+---------+-----+
| c1      |   1 |
| c2      |   2 |
| c3      |   0 |
+---------+-----+

Live Demo

【讨论】:

以上是关于SQL Server:交叉应用 - 为 NULL 结果记录 0的主要内容,如果未能解决你的问题,请参考以下文章

OPENJSON 与 NULL 值交叉应用 (SQL)

SQL Server 交叉应用

SQL Server 交叉应用不起作用?

SQL Server交叉表应用示例

SQL Server 交叉应用性能问题

如何在 SQL Server 的交叉应用联接中指定列名