8

我正在尝试获取某个区域可用的 itemid 的百分比。使用我的查询,我得到一个错误ORA-00937: not a single-group group function

所有细节:

我有这两张表:

ALLITEMS
---------------
ItemId  | Areas
---------------
1       | EAST
2       | EAST
3       | SOUTH
4       | WEST

CURRENTITEMS
---------------
ItemId
---------------
1
2
3

并想要这个结果:

---------------
Areas| Percentage
---------------
EAST   | 50  --because ItemId 1 and 2 are in currentitems, so 2 items divided by the total 4 in allitems = .5
SOUTH  | 25   --because there is 1 item in currentitems table that are in area SOUTH (so 1/4=.25)
WEST   | 0  --because there are no items in currentitems that are in area WEST

DDL:

drop table allitems;
drop table currentitems;

Create Table Allitems(ItemId Int,areas Varchar2(20));
Create Table Currentitems(ItemId Int);
Insert Into Allitems(Itemid,Areas) Values(1,'east');
Insert Into Allitems(ItemId,areas) Values(2,'east');
insert into allitems(ItemId,areas) values(3,'south');
insert into allitems(ItemId,areas) values(4,'east');

Insert Into Currentitems(ItemId) Values(1);
Insert Into Currentitems(ItemId) Values(2);
Insert Into Currentitems(ItemId) Values(3);

我的查询:

Select  
areas,
(
Select 
Count(Currentitems.ItemId)*100 / (Select Count(ItemId) From allitems inner_allitems Where inner_allitems.areas = outer_allitems.areas )
From 
Allitems Inner_Allitems Left Join Currentitems On (Currentitems.Itemid = Inner_Allitems.Itemid) 
Where inner_allitems.areas = outer_allitems.areas
***group by inner_allitems.areas***
***it worked by adding the above group by***
) "Percentage Result"
From 
allitems outer_allitems
Group By 
areas

错误:

Error at Command Line:81 Column:41 (which is the part `(Select Count(ItemId) From allitems inner_allitems Where inner_allitems.areas = outer_allitems.areas )`)
Error report:
SQL Error: ORA-00937: not a single-group group function

当我在 SQL Server 中运行完全相同的查询时,它工作正常。如何在 Oracle 中解决此问题?

4

7 回答 7

11

分析是您的朋友:

SELECT DISTINCT
       areas
      ,COUNT(currentitems.itemid)
       OVER (PARTITION BY areas) * 100
       / COUNT(*) OVER () Percentage
FROM allitems, currentitems
WHERE allitems.itemid = currentitems.itemid(+);
于 2010-01-28T05:09:15.317 回答
4

只是为了它,一种无需分析的方式。

Jeffrey 的解决方案需要一个 DISTINCT,因为areas. 该allitems表实际上是一个相交表currentitems和一个假定areas表。在以下查询中,这由内联视图表示ai。还有另一个内联视图tot,它为我们提供了 中的记录总数allitems。此计数必须包含在 GROUP BY 子句中,因为它不是聚合投影仪。

SQL> select ai.areas
  2         , (count(currentitems.itemid)/tot.cnt) * 100 as "%"
  3  from
  4      ( select count(*) as cnt from allitems ) tot
  5      , ( select distinct areas as areas from allitems ) ai
  6      , currentitems
  7      , allitems
  8  where allitems.areas = ai.areas
  9  and   allitems.itemid = currentitems.itemid(+)
 10  group by ai.areas, tot.cnt
 11  /

AREAS                         %
-------------------- ----------
east                         50
south                        25
west                          0

SQL>

我不知道这种方法是否会比 Jeffrey 的解决方案执行得更好:它很可能会执行得更差(分析查询肯定有更少的一致获取)。这很有趣,因为它更清楚地突出了问题。

于 2010-01-28T09:58:56.820 回答
1

这是一个快速的第一关:

select ai.areas,
       (sum(cnt) / max(tot)) * 100 "Percentage Result"
  from (select ai.itemid,
               ai.areas,
               count(ci.itemid) cnt,
               count(ai.areas) over () tot
          from allitems ai
               left outer join
               currentitems ci on (ai.itemid = ci.itemid)
        group by ai.itemid, ai.areas
       ) ai
group by ai.areas

此外,在您的测试数据中,您的 itemid 4 需要更改为 west。

于 2010-01-27T22:12:29.610 回答
1

对原始查询稍作修改:

Select  
areas,
(
Select 
Count(*)
From 
Allitems Inner_Allitems Left Join Currentitems On (Currentitems.Itemid = Inner_Allitems.Itemid) 
Where inner_allitems.areas = outer_allitems.areas
) *100 / (Select Count(*) From allitems ) as percentage
From allitems outer_allitems
Group By areas
于 2010-01-27T23:22:55.617 回答
0

使用组“按子句”:

Select department_id, min(salary)
From employees
Group By department_id
Having min(salary) >
(
    Select min(salary)
    From employees
    Where department_id <> 50
);
于 2020-04-14T11:25:40.563 回答
0

我想即使这也有帮助:

SELECT
    distinct areas,
    NVL(x.count_item * 100,0) AS Percentage
FROM
    allitems a
    LEFT OUTER JOIN (
        SELECT
            ( COUNT(a.itemid) / (
                SELECT
                    COUNT(*)
                FROM
                    allitems
            ) ) AS count_item,
            areas AS avl_areas
        FROM
            allitems       a
            INNER JOIN currentitems   c ON a.itemid = c.itemid
        GROUP BY
            areas
    ) x ON x.avl_areas = a.areas
;
于 2020-12-10T10:28:44.737 回答
0

我发现一个可行的解决方法(虽然我认为这里有一个错误)是这样的:

-- Doesn't work (though it really should):
select 
  count(*),
  (select count(*) from dual)
from dual;

-- Works
select 
  count(*),
  (select count(*) from dual)
from dual
group by grouping sets (());

小提琴手

于 2021-08-31T14:07:38.290 回答