在SQL中对多个表进行求和和计数

时间:2014-10-31 19:26:35

标签: sql db2-luw

我有3个表,我需要从中选择和汇总数据。

Table: IDEA  
REFERENCE SL   
128       SL1  
200       SL1  
201       SL2  
205       SL3 



Table: ACCT1  
IDEA_REF  ACCTS  
128       5  
128       2  
200       3  
205       4  

Table: ACCT2  
IDEA_REF  ACCTS  
201       3  
205       4 
205       3

我需要做的是从SL排序摘要,并使用两个表的ACCTS字段中的总计。

这是我到目前为止使用的SQL:

SELECT I.SL AS SL, COUNT(DISTINCT I.REFERENCE) AS NO,  
    SUM(CASE WHEN A1.IDEA_REF=I.REFERENCE THEN A1.ACCTS ELSE 0 END) AS ACCT1,  
    SUM(CASE WHEN A2.IDEA_REF=I.REFERENCE THEN A2.ACCTS ELSE 0 END) AS ACCT2  
    FROM IDEA I  
    LEFT JOIN ACCT1 A1 ON A1.IDEA_REF=I.REFERENCE  
    LEFT JOIN ACCT2 A2 ON A2.IDEA_REF=I.REFERENCE  
    WHERE A2.IDEA_REF IN I.REFERENCE OR A1.IDEA_REF IN I.REFERENCE  
    GROUP BY I.SL  

我发现的问题是ACCT1和ACCT2表中有多个值并且引用了IDEA表。以下是此查询的结果:

SL  NO  ACCT1  ACCT2  
SL1 2   10      0  
SL2 1    0      3  
SL3 1    8      7  

SL3行将ACCT1和ACCT2值加两次。我似乎无法找到适当的方法来添加适当的次数。

所需的输出是:

SL   NO   ACCT1  ACCT2
SL1  2    10     0  
SL2  1     0     3  
SL3  1     4     7

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:0)

您要求三个单独的聚合,但是您尝试在一个查询中计算它们。

要获得NO(不同项目的数量),您可以

SELECT SL,
       COUNT(*) AS NO
  FROM IDEA
 GROUP BY SL

要获得ACCT1项,您可以这样做:

SELECT SL,
       SUM(ACCTS) AS ACCT1
  FROM IDEA
  JOIN ACCT1 ON IDEA.REFERENCE = ACCT1.IDEA_REF
GROUP BY SL

以同样的方式,您可以获得ACCT2

SELECT SL,
       SUM(ACCTS) AS ACCT2
  FROM IDEA
  JOIN ACCT2 ON IDEA.REFERENCE = ACCT2.IDEA_REF
GROUP BY SL

然后,您需要在SL上将所有这些聚合查询连接在一起以获取结果集。由于您在某些聚合中缺少条目,因此您需要LEFT中的LEFT JOINCOALESCE()项。

SQL Fiddle

这是全部查询

SELECT Q.SL, NO, 
       COALESCE(ACCT1,0) AS ACCT1, 
       COALESCE(ACCT2,0) AS ACCT2
  FROM (
        SELECT SL,
               COUNT(*) AS NO
          FROM IDEA
          GROUP BY SL
       ) Q
   LEFT JOIN (
          SELECT SL,
                 SUM(ACCTS) AS ACCT1
            FROM IDEA
            JOIN ACCT1 ON IDEA.REFERENCE = ACCT1.IDEA_REF
           GROUP BY SL
        ) R ON Q.SL = R.SL
   LEFT JOIN (
            SELECT SL,
                   SUM(ACCTS) AS ACCT2
              FROM IDEA
              JOIN ACCT2 ON IDEA.REFERENCE = ACCT2.IDEA_REF
            GROUP BY SL
         ) S ON Q.SL = S.SL

The result is what you are looking for

|  SL | NO | ACCT1 | ACCT2 |
|-----|----|-------|-------|
| SL1 |  2 |    10 |     0 |
| SL2 |  1 |     0 |     3 |
| SL3 |  1 |     4 |     7 |

看看这是如何工作的?你必须分别做每个聚合。

如果您使用的DBMS不知道JOIN ... USING()语法,请改为使用ON Q.SL = R.SL或相应的ON子句。请参阅编辑,并查看此小提琴:http://sqlfiddle.com/#!2/63aa1/3/0

答案 1 :(得分:0)

我认为子查询的性能不会超过count,我也应避免在同一个表上多次连接

SELECT
     i.SL,
     COUNT(DISTINCT i.SL) NO,
     COALESCE(SUM(a.sum1), 0) act1,
     COALESCE(SUM(b.sum2), 0) act2
FROM
     IDEA i
LEFT JOIN
     (
     SELECT
         IDEA_REF,
         SUM(ACCTS) sum1
     FROM
         ACCT1
     GROUP BY IDEA_REF
     ) a
     ON i.REFERENCE = a.IDEA_REF
LEFT JOIN
     (
     SELECT
         IDEA_REF,
         SUM(ACCTS) sum2
     FROM
         ACCT2
     GROUP BY IDEA_REF
     ) b
     ON i.REFERENCE = b.IDEA_REF
GROUP BY i.SL

SQL Fiddle

结果相同但表扫描次数较少

答案 2 :(得分:0)

您可以使用UNION ALL

来实现结果
SELECT 
    COMB.SL AS SL, 
    COUNT(DISTINCT COMB.REFERENCE) AS NO, 
    sum(T1) as ACCT1, 
    sum(T2) ACCT2
FROM (
    SELECT 
        I.*,A1.ACCTS as t1,0 as t2
    FROM 
        IDEA I  
    LEFT JOIN 
        ACCT1 A1 ON A1.IDEA_REF=I.REFERENCE  
    UNION ALL
    SELECT 
        I.*,0 as t1,A2.ACCTS as t2
    FROM 
        IDEA I  
    LEFT JOIN 
        ACCT2 A2 ON A2.IDEA_REF=I.REFERENCE
) as COMB
GROUP BY 
    COMB.SL