【问题标题】:SQL Server: Cross-apply - record 0 for NULL resultsSQL Server:交叉应用 - 为 NULL 结果记录 0
【发布时间】: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

标签: sql-server cross-apply


【解决方案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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多