2010-01-27 25 views
5

我正在嘗試獲取某個區域中可用的itemid的百分比。 使用我的查詢,我得到一個錯誤ORA-00937: not a single-group group function如何解決ORA-00937:計算百分比時不是單組功能?

所有的細節:

我有這兩個表:

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中修復此問題?

+0

感謝您的好評。不同的方式來做到這一點!謝謝。我還發現通過添加一個group(編輯該問題,查看我的查詢中的「***」),它也可以工作。 – Liao 2010-01-28 08:09:34

回答

7

Analytics(分析)是你的朋友:

SELECT DISTINCT 
     areas 
     ,COUNT(currentitems.itemid) 
     OVER (PARTITION BY areas) * 100 
    /COUNT(*) OVER() Percentage 
FROM allitems, currentitems 
WHERE allitems.itemid = currentitems.itemid(+); 
+1

他提到SQL Server和Oracle,可能查詢必須是可移植的,這是供應商不可知論的。 – 2010-01-28 19:25:59

+3

便攜性shmortability :) – 2010-01-29 01:20:59

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個需要改變向西。

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 
3

只爲它赫克,這樣做沒有分析的方法。

由於重複areas,Jeffrey的解決方案需要DISTINCT。 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> 

我不知道這種做法是否會表現得比傑弗裏的更好的解決方案:它很可能會表現更差(在分析查詢肯定有較少的一致獲取)。這很有趣,因爲它更清楚地突出了問題。

+1

不過,感謝您的意見。我今天沒有時間,但我明天會測試所有的優秀答案! – Liao 2010-01-28 10:21:39