我是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结果中每个名称有一个结果。
答案 0 :(得分:2)
在Oracle中按照这种方式进行分组并不习惯,但如果需要,仍然可以。相反,更好的做法和我的建议是按name
和id
分组,产生两行,每行一个。
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