2010-01-27 3 views
5

Ich versuche, einen Prozentsatz der Artikel-ID zu erhalten, die in einem bestimmten Bereich verfügbar sind. Mit meiner Anfrage, bekomme ich einen Fehler ORA-00937: not a single-group group functionWie löst man ORA-00937: keine Gruppenfunktion für eine einzelne Gruppe bei der Berechnung des Prozentsatzes?

Alle Details:

Ich habe diese beiden Tabellen:

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

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

und dieses Ergebnis wollen:

--------------- 
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 

Die 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); 

Meine Suche:

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 

Der Fehler:

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 

Wenn ich genau die gleiche Abfrage in SQL Server ausführen, funktioniert es gut. Wie behebe ich das in Oracle?

+0

Danke für die tollen Antworten. Verschiedene Möglichkeiten, es zu tun! Vielen Dank. Ich fand auch, dass es funktioniert, wenn Sie eine Gruppe hinzufügen (die Frage bearbeitet, in Meine Abfrage nach "***" gesucht). – Liao

Antwort

7

Analytics sind Freund:

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

Er erwähnt SQL Server und Oracle, vielleicht muss die Abfrage tragbar sein, das ist herstellerunabhängig. –

+3

Portabilität Shmortability :) –

1

Hier ist ein schneller erster Pass:

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 

Auch nach Westen geändert wird in Testdaten Ihre itemid 4 benötigt.

1

Eine leichte Änderung Ihrer ursprünglichen Abfrage:

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

nur für das Heck von ihm, eine Art und Weise, ohne Analytik zu tun.

Jeffreys Lösung brauchte wegen der Duplizierung von areas ein DISTINCT. Die allitems Tabelle ist eigentlich eine Kreuztabelle zwischen currentitems und einer mutmaßlichen areas Tabelle. In der folgenden Abfrage wird dies durch die Inline-Sicht ai dargestellt. Es gibt eine weitere Inline-Ansicht tot, die uns die Gesamtzahl der Datensätze in allitems angibt. Diese Anzahl muss in die GROUP BY-Klausel aufgenommen werden, da es sich nicht um einen aggregierenden Projektor handelt.

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> 

Ich weiß nicht, ob dieser Ansatz besser als Jeffrey-Lösung durchführen würde: es möglicherweise schlechter durchführen wird (die Analytik Abfrage hat sicherlich weniger konsistent wird). Es ist interessant, weil es die Probleme deutlicher hervorhebt.

+1

Trotzdem danke für Ihre Eingabe. Ich habe heute keine Zeit, aber ich werde morgen alle guten Antworten testen! – Liao

Verwandte Themen