SUM按列分组依据SQL

时间:2015-09-03 07:53:49

标签: sql-server group-by sql-function

我有以下数据:

+----------------+--------------+-----+
| StgDescription |      ID      | Amt |
+----------------+--------------+-----+
| A              | OA17         |  11 |
| A              | OA17         |  11 |
| A              | OA17         |  11 |
| A              | OA17         |  11 |
| B              | ZA47/ A      |  12 |
| B              | ZA47/ A      |  12 |
| B              | ZA47/ B      |  10 |
| B              | ZA47/ B      |  10 |
| B              | ZA48/ A      |  14 |
| B              | ZA48/ F      |  10 |
| B              | ZA48 /G      |  13 |
| B              | ZA48 /H      |  10 |
| B              | ZA48/ I      |  15 |
| B              | ZA48/ J      |  10 |
| B              | ZA48/ K      |  16 |
| B              | ZA48/ L      |  10 |
| c              | FA01LM100340 |  10 |
| c              | PA53 AE      |  10 |
+----------------+--------------+-----+

我想以下列格式生成报告。对于相同的StgDescription,金额应为ID的总和。

+----------------+-----+
| StgDescription | Amt |
+----------------+-----+
| a              |  11 |
| b              | 120 |
| c              |  20 |
+----------------+-----+

我已经在查询后写了这个结果:

  WITH CTE AS(
  SELECT 
     distinct
      s.StgDescription
     ,p.ID
        ,Amt

  FROM [DinDb].[dbo].[tblTvlTransaction] t
  JOIN tblstgmaster s on t.StgId=s.StgId
  JOIN tblProjDocSt p on t.TDocID=p.DocId
  JOIN  [PdasDb].[dbo].[tblIDmaster] f ON p.ID=f.ID
  where OptAuthoDateTime between '2015-07-27 00:00:00' and '2015-09-01 00:00:00')
  select  StgDescription,sum(AMT) from cte group by  StgDescription

还有其他有效的选择吗?

4 个答案:

答案 0 :(得分:1)

首先在cte中删除重复项,然后GROUP BY如:

WITH cte AS (
   SELECT DISTINCT StgDescription, ID, Amt 
   FROM your_tab
)
SELECT 
   StgDescription,
   Amt = SUM(Amt)
FROM cte
GROUP BY StgDescription;

OR:

WITH cte AS (
   SELECT StgDescription, ID, Amt 
   FROM your_tab
   GROUP BY StgDescription, ID, Amt
)
SELECT 
   StgDescription,
   Amt = SUM(Amt)
FROM cte
GROUP BY StgDescription;

答案 1 :(得分:1)

我希望您从查询中获取数据,而不是从表中获取数据。因此冗余地存储数据并不好。并且不能命名列ID,而列ID不是表中行的唯一标识符。

您的数据问题是您有重复项,这会阻止您直接获得总和。因此,请先使用DISTINCT使您的数据独一无二。

如果此数据来自查询,则只需在DISTINCT关键字后添加SELECT即可。如果没有,请使用派生表(即子查询),从表中选择不同的记录。

select stgdescription, sum(amt)
from
(
  select distinct stgdescription, id, amt
  from mydata
) distinct_data
group by stgdescription;

您可能希望将stgdescription替换为lower(stgdescription),但是,如果stgdescription可以是'A'或'a',并且您希望将它们视为相同。

答案 2 :(得分:0)

我保持尽可能简单,就像这样:

select StgDescription, sum(Amt) from
(
select distinct StgDescription, ID, Amt from tablename
) a
group by StgDescription

希望它有所帮助!

答案 3 :(得分:0)

我怀疑您的重复内容来自[tblTvlTransaction],因此,我会将此表格移除为JOIN并使用EXISTS来检查记录是否存在。基本上FROM子句中的唯一表是您实际需要数据的表:

SELECT  s.StgDescription, p.ID, s.Amt
FROM    tblstgmaster AS s
        INNER JOIN tblProjDocSt p on 
            t.TDocID = p.DocId
        INNER JOIN [PdasDb].[dbo].[tblIDmaster] AS f 
            ON p.ID = f.ID
WHERE   EXISTS
        (   SELECT  1
            FROM    [DinDb].[dbo].[tblTvlTransaction] AS t
            WHERE   t.OptAuthoDateTime BETWEEN '2015-07-27 00:00:00' AND '2015-09-01 00:00:00'
            AND     t.StgId = s.StgId
        );

EXISTS的优点是它可以使用半连接,这实际上意味着而不是从事务表中拉回所有行,它会在找到一个匹配时立即停止搜索/扫描记录。这应该不会重复,因此您可以直接执行SUM

SELECT  s.StgDescription, Amount = SUM(s.Amt)
FROM    tblstgmaster AS s
        INNER JOIN tblProjDocSt p on 
            t.TDocID = p.DocId
        INNER JOIN [PdasDb].[dbo].[tblIDmaster] AS f 
            ON p.ID = f.ID
WHERE   EXISTS
        (   SELECT  1
            FROM    [DinDb].[dbo].[tblTvlTransaction] AS t
            WHERE   t.OptAuthoDateTime BETWEEN '2015-07-27 00:00:00' AND '2015-09-01 00:00:00'
            AND     t.StgId = s.StgId
        )
GROUP BY s.StgDescription;