SQL Server中多列的聚合函数

时间:2016-06-21 08:43:40

标签: sql sql-server sql-server-2008

我在#temp表中有以下数据:

Id  code       Fname       CompanyId    FieldName         Value
----------------------------------------------------------------
465 00133   JENN WILSON       1           ERA              1573
465 00133   JENN WILSON       1           ESHIFTALLOW      3658
465 00133   JENN WILSON       1           NETPAY          51560

我想做以下操作,即

One Row将在两列上添加,ERA + ESHIFTALLOW 其他行将减法&添加三列,NETPAY - ERA + ESHIFTALLOW 我曾尝试在SQL Server中使用case语句。

以下是所需的输出

Field1= ERA + ESHIFTALLOW& Filed2=NETPAY - ERA + ESHIFTALLOW

Id  code       Fname       CompanyId    FieldName         Value
----------------------------------------------------------------
465 00133   JENN WILSON       1           Field1          5231
465 00133   JENN WILSON       1           Filed2          46329

我曾尝试使用SQL SERVER Case Statement但没有获得正确的输出 SQL查询:Aggregate option in SQL Server CASE statement

3 个答案:

答案 0 :(得分:3)

我看到至少有两种方法可以获得这些结果。分组或轴心

在下面的示例中,显示了2种方法。

CREATE TABLE #Temp (Id INT, code VARCHAR(5), Fname VARCHAR(20), CompanyId INT, FieldName VARCHAR(20), Value INT);

insert into #Temp (Id, code, Fname, CompanyId, FieldName, Value)
values 
(465,00133,'JENN WILSON',1,'ERA',1573),
(465,00133,'JENN WILSON',1,'ESHIFTALLOW',3658),
(465,00133,'JENN WILSON',1,'NETPAY',51560);

with Q AS (
  SELECT Id, code, Fname, CompanyId, 
  sum(case when FieldName = 'ERA' then Value end) as ERA,
  sum(case when FieldName = 'ESHIFTALLOW' then Value end) as ESHIFTALLOW,
  sum(case when FieldName = 'NETPAY' then Value end) as NETPAY
  from #Temp
  group by Id, code, Fname, CompanyId
)
select Id, code, Fname, CompanyId, 'Field1' as FieldName, (ERA +  ESHIFTALLOW) as Value from Q
union all
select Id, code, Fname, CompanyId, 'Field2', (NETPAY - ERA +  ESHIFTALLOW) from Q
;

with Q AS (
  SELECT Id, code, Fname, CompanyId, 
  (ERA +  ESHIFTALLOW) as Field1,
  (NETPAY - ERA +  ESHIFTALLOW) as Field2
  FROM (SELECT * FROM #Temp) s
  PIVOT ( SUM(VALUE) FOR FieldName IN (ERA, ESHIFTALLOW, NETPAY)) p
)
select Id, code, Fname, CompanyId, 'Field1' as FieldName, Field1 as Value from Q
union all
select Id, code, Fname, CompanyId, 'Field2', Field2 from Q
;

请注意,使用SUM(VALUE)代替MAX(VALUE)。在这种情况下,它将产生相同的结果。它真的只是一个选择。

答案 1 :(得分:2)

严重依赖LukStorms'回答,您可以使用PIVOT和UNPIVOT来获得您想要的结果:

CREATE TABLE #Temp 
    (Id INT, Code VARCHAR(5), Fname VARCHAR(20), CompanyId INT, FieldName VARCHAR(20), Value INT);

INSERT INTO #Temp 
    (Id, Code, Fname, CompanyId, FieldName, Value)
VALUES 
    (465,00133, 'JENN WILSON', 1, 'ERA', 1573),
    (465,00133, 'JENN WILSON', 1, 'ESHIFTALLOW', 3658),
    (465,00133, 'JENN WILSON', 1, 'NETPAY', 51560);


SELECT Id, Code, Fname, CompanyId, FieldName, Value 
FROM (
    SELECT Id, Code, Fname, CompanyId, 
    ERA +  ESHIFTALLOW AS Field1,
    NETPAY - ERA +  ESHIFTALLOW AS Field2
    FROM (
        SELECT * 
        FROM #Temp
    ) AS s
    PIVOT ( 
        SUM(Value) 
        FOR FieldName IN (ERA, ESHIFTALLOW, NETPAY)
    ) AS p
) AS r
UNPIVOT (
    Value 
    FOR FieldName IN (Field1, Field2)
) AS u
;

答案 2 :(得分:1)

我不知道这个解决方案是否最接近效率,但它应该有效:

SELECT 
  BASE.*,
  ERA.Value AS ERA,
  ESALLOW.Value AS ESHIFTALLOW,
  ERA.Value + ESALLOW.Value AS Field1,
  etc...
FROM (
   SELECT DISTINCT Id, code, Fname, CompanyId
   FROM #TEMP ) BASE
LEFT OUTER JOIN (
   SELECT Id, Value
   FROM #TEMP
   WHERE FieldName = 'ERA' ) ERA
ON BASE.Id = ERA.Id
LEFT OUTER JOIN (
   SELECT Id, Value
   FROM #TEMP
   WHERE FieldName = 'ESHIFTALLOW' ) ESALLOW
ON BASE.Id = ESALLOW.Id

这为您提供了一个简单的表,它在单独的列中具有每种类型的值,而不是在单独的行中。这使计算成为可能。