SQL,组合同一个表的两个聚合

时间:2017-03-29 04:51:14

标签: mysql sql oracle stored-procedures aggregate

我有下表,其中包含operator针对每个department的特定date中特定target_type执行的操作数。 sum1sum2是特定日期的操作1和操作2的编号,有问题的操作的解释由operation_type列表示。

statistic_id | department | operator | operation_type | target_type | sum1 | sum2 | date |

我会查询该表,以便按operation_type 1department 1分组的特定时间段operator收集operation_type的统计信息,如下所示

SELECT operator, target_type, SUM(sum1) AS op1, SUM(sum2) AS op2 FROM statistics
WHERE
  department = 1 AND
  operation_type = 1 AND
  (date BETWEEN in_start_date AND in_end_date)
GROUP BY operator, target_type
ORDER BY operator, target_type;

同样,我会查询该表,以便按照相同标准分组的同一部门和时间间隔收集operation_type 2的统计信息

SELECT operator, target_type, SUM(sum1) AS op3, SUM(sum2) AS op4 FROM statistics
WHERE
  department = 1 AND
  operation_type = 2 AND
  (date BETWEEN in_start_date AND in_end_date)
GROUP BY operator, target_type
ORDER BY operator, target_type;

我想结合查询结果,所以我会得到像

这样的结果
operator | target_type | op1 | op2 | op3 | op4

如何通过根据一些常见和一些不同的标准聚合不同的列,然后按同一组列进行分组,将自己与表连接起来?

2 个答案:

答案 0 :(得分:1)

在总和中使用条件聚合:

SELECT operator,
       target_type,
       SUM(CASE WHEN operation_type = 1 THEN sum1 ELSE 0 END) AS op1,
       SUM(CASE WHEN operation_type = 1 THEN sum2 ELSE 0 END) AS op2,
       SUM(CASE WHEN operation_type = 2 THEN sum1 ELSE 0 END) AS op3,
       SUM(CASE WHEN operation_type = 2 THEN sum2 ELSE 0 END) AS op4
FROM statistics
WHERE department = 1 AND
      date BETWEEN in_start_date AND in_end_date
GROUP BY operator, target_type
ORDER BY operator, target_type

这会在整个表格中进行一次传递,并根据operation_type1还是2有条件地获取所需的总和。请注意,CASE表达式仅包含operation_type,而不包括部门或日期。这样做的原因是因为您的两个原始预期查询都共享这些相同的WHERE条件,因此我们无需移动它们。

答案 1 :(得分:0)

select operator, target_type, op1, op2, op3, op4
from (query 1) a
full outer join (query 2) b
on (a.operator=b.operator and a.target_type=b.target_type)
order by operator, target_type;

现在,两个查询都非常相似(相同的日期范围)。你可以只做一个查询:

SELECT operator, target_type, SUM(case when operation_type=1 then sum1 else 0 end) AS op1, SUM(case when operation_type=1 then sum2 else 0 end) AS op2,
SUM(case when operation_type=2 then sum1 else 0 end) AS op3, SUM(case when operation_type=2 then sum2 else 0 end) AS op4
 FROM statistics
WHERE
  department = 1 AND
  operation_type in (1,2) AND
  (date BETWEEN in_start_date AND in_end_date)
GROUP BY operator, target_type
ORDER BY operator, target_type;