组合BY和每个结果的多个计数

时间:2016-04-26 00:48:31

标签: oracle

我是Oracle的新手,希望结果包含基于值的多个计数。例如:

SELECT p.name, count(f.id) as eaten_apples, count(f.id) as eaten_oranges
FROM food f, people p
WHERE f.pid=p.pid
AND f.id = 'apple' OR f.id = 'orange'
GROUP BY p.name;
显然,有两次计数(f.id)会产生相同的结果,但是希望每种食物吃一次。苹果和橘子。预期结果可能如下所示:

[0] => 
  name : john
  eaten_apples:  3
  eaten_oranges: 1
[1] => 
  name : sam
  eaten_apples:  0
  eaten_oranges: 9
...

换句话说,每个结果有多个计数。在这种情况下,一个人吃的食品数量。

我的查询现在每个名称返回两个结果,我可以在SQL之外组合,但我希望SQL结果中每个名称有一个结果。

2 个答案:

答案 0 :(得分:2)

在Oracle中按照这种方式进行分组并不习惯,但如果需要,仍然可以。相反,更好的做法和我的建议是按nameid分组,产生两行,每行一个。

SELECT p.name, f.id, count(1) as eaten_fruit
from food f, people p
WHERE f.pid=p.pid
AND (
       f.id = 'apple' OR 
       f.id = 'orange'
     )
GROUP BY p.name, f.id;

我相信让应用程序处理上述数据的读取更有效,但正如我所指出的,还有重新格式化的选项。存在a number of ways to transpose these row based results into columns,另一个解决方案尝试其中之一。我的偏好方法是使用专门为此目的引入的PIVOT operator。要以您想要的格式获得结果,您可以将行转换为以下列:

select name, id from
                     (
                       select p.name, f.id
                       from food f, people p
                       where f.pid = p.pid
                       and f.id in ('apple','orange')
                     )
pivot (
          count(id)
          for id in (
                      'apple' as eaten_apples,
                      'orange' as eaten_oranges
                    )
      );

它会起作用但不习惯。

答案 1 :(得分:0)

这是一个选项,可以在一条记录中给出每人吃苹果和橙子的数量:

WITH cte AS
(
    SELECT p.name, f.id
    FROM people p LEFT JOIN food f
        ON f.pid = p.pid
)

SELECT t1.name, COALESCE(t1.aCount, 0) AS eaten_apples,
    COALESCE(t2.oCount, 0) AS eaten_oranges
FROM people AS p
LEFT JOIN
(
    SELECT name, COUNT(name) AS aCount
    FROM cte
    WHERE id = 'apple'
    GROUP BY name
) AS t1
    ON p.name = t1.name
LEFT JOIN
(
    SELECT name, COUNT(name) AS oCount
    FROM cte
    WHERE id = 'orange'
    GROUP BY name
) AS t2
    ON p.name = t2.name