【问题标题】:SQL COUNT on 3 tables with JOIN使用 JOIN 对 3 个表进行 SQL COUNT
【发布时间】:2017-08-11 15:03:15
【问题描述】:

我在一个数据库中有 4 个表。仓库包含客户拥有的盒子,盒子里有文件。有Client 表、Warehouse 表、Boxes 表和Files 表。

所以Client 表有WarehouseID 作为外键,Boxes 表有ClientID 作为外键,Files 表有BoxID 作为外键。我想计算每个客户在我的查询中拥有的盒子和文件的数量,以及进出仓库的盒子数量。 BoxesFiles 表上的Status 字段确定箱子和文件是进出仓库。我在盒子上运行以下查询并且数字是正确的:

SELECT
    [c].[ClientID],
    [c].[Name] AS [ClientName],
    [w].[Name] AS [WarehouseName],
    COUNT(DISTINCT [b].[BoxID]) AS [BoxCount],
    SUM(CASE WHEN [b].[Status] = @IN THEN 1 ELSE 0 END)) AS [BoxesIn],
    SUM(CASE WHEN [b].[Status] = @OUT THEN 1 ELSE 0 END) AS [BoxesOut],
    SUM(CASE WHEN [b].[DestructionDate] <= GETDATE() THEN 1 ELSE 0 END) AS [BoxesForDestruction],
FROM [Clients] AS [c] INNER JOIN [Boxes] AS [b]
  ON [c].[ClientID] = [b].[ClientID]
INNER JOIN [Warehouses] AS [w]
  ON [c].WarehouseID = [w].[WarehouseID]
WHERE [c].[ClientID] = @ClientID
GROUP BY
  [c].[ClientID],
  [c].[Name],
  [w].[Name]

这会产生以下输出:

ClientID | ClientName | WarehouseName | BoxCount | BoxesIn | BoxesOut | BoxesForDestruction
1        | ACME Corp. | FooFactory    | 22744    | 22699   | 45       | 7888 

计数的输出是正确的。当我将Files 表添加到INNER JOIN 时,数字就会膨胀。这是 SQL:

SELECT
    [c].[ClientID],
    [c].[Name] AS [ClientName],
    [w].[Name] AS [WarehouseName],
    COUNT(DISTINCT [b].[BoxID]) AS [BoxCount],
    COUNT(DISTINCT [f].[FileID]) AS [FileCount], -- *NEW*
    SUM(CASE WHEN [b].[Status] = @IN THEN 1 ELSE 0 END)) AS [BoxesIn],
    SUM(CASE WHEN [b].[Status] = @OUT THEN 1 ELSE 0 END) AS [BoxesOut],
    SUM(CASE WHEN [b].[DestructionDate] <= GETDATE() THEN 1 ELSE 0 END) AS [BoxesForDestruction],
FROM [Clients] AS [c] INNER JOIN [Boxes] AS [b]
  ON [c].[ClientID] = [b].[ClientID]
INNER JOIN [Warehouses] AS [w]
  ON [c].[WarehouseID] = [w].[WarehouseID]
INNER JOIN [Files] AS [f]      -- *NEW*
  ON [b].[BoxID] = [f].[BoxID] -- *NEW*
WHERE [c].[ClientID] = @ClientID
GROUP BY
  [c].[ClientID],
  [c].[Name],
  [w].[Name]

这给了我下面的计数输出(我省略了前 3 列,因为它们不相关):

BoxCount | FilesCount | BoxesIn | BoxesOut | BoxesForDestruction 
19151    | 411961     | 411381  | 580      | 144615       

FilesCount 是正确的,但其他数字是关闭的。我知道为什么会这样,但我不知道如何解决它。由于在框和文件上的连接返回了多行,因此创建了额外的行。执行SUM 时,额外的行会增加计数。由于仓库只有一行,因此该连接不会影响计数。如何修改我的查询以获取正确数量的进出仓库的文件和盒子?

【问题讨论】:

    标签: sql-server database join sum


    【解决方案1】:

    join 为右侧表格中的每一行重复左侧表格中的每一行。如果您合并多个连接,则某些行将被重复计算。一种解决方案是将计数移动到子查询中。例如:

    select  *
    from    table1 t1
    join    (
            select  table1_id
            ,       count(*)
            from    table2
            group by
                    table1_id
            ) t2
    on      t2.table1_id = t1.id
    join    (
            select  table1_id
            ,       count(*)
            from    table3
            group by
                    table1_id
            ) t3
    on      t3.table1_id = t1.id
    

    【讨论】:

      【解决方案2】:

      正如 Andomar 所说,除了 Count(*) 之外,我还包括了“as myColumnOne”和“myColumnTwo”,因为它是 SQL Server 2018 所必需的:

       select  *
      from    table1 t1
      join    (
              select  table1_id
              ,       count(*) as myColumnOne
              from    table2
              group by
                      table1_id
              ) t2
      on      t2.table1_id = t1.id
      join    (
              select  table1_id
              ,       count(*) as myColumnTwo
              from    table3
              group by
                      table1_id
              ) t3
      on      t3.table1_id = t1.id
      

      【讨论】:

      • 没有 SQL Server 2018 版本 - 我们有 2012、2014、2016、2017 和 2019 - 任君选择
      • v17.9.1,出现的年份是 2018。关键是您需要包含列名才能在新版本中使用。 =)
      • v17.9.1 是 SQL Server Management Studio 的版本 - GUI 管理工具 - 不是 SQL Server 数据库引擎 b>(在了解给定问题的可用或尚未可用的功能时,这才是真正重要的)。对您的数据库引擎运行SELECT @@VERSION - THAT 是我们需要了解的版本 - 而不是您使用的管理工具版本.....
      • 谢谢。版本为:Microsoft SQL Azure (RTM) - 12.0.2000.8 Oct 1 2020 18:48:35 Copyright (C) 2019 Microsoft Corporation
      猜你喜欢
      • 1970-01-01
      • 2021-10-21
      • 2011-11-18
      • 1970-01-01
      • 2014-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      相关资源
      最近更新 更多