2010-01-27 11 views
5

Sto cercando di ottenere una percentuale di itemid disponibili in una determinata area. Utilizzando la mia domanda, ottengo un errore ORA-00937: not a single-group group functionCome risolvere ORA-00937: non una funzione di gruppo a gruppo singolo quando si calcola la percentuale?

Tutti i dettagli:

Ho questi due tabelle:

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

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

e vogliono questo risultato:

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

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

mia domanda:

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 

L'errore:

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 

Quando eseguo la stessa identica query in SQL Server, funziona benissimo. Come posso risolvere questo problema in Oracle?

+0

Grazie per le grandi risposte. Diversi modi per farlo! Grazie. Ho anche scoperto che aggiungendo un gruppo (modificato la domanda, guardate in My Query per "***") funziona anche. – Liao

risposta

7

Analytics sono tuo amico:

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

Menziona SQL Server e Oracle, forse la query deve essere portatile, ovvero indipendente dal fornitore. –

+3

portabilità shmortability :) –

1

ecco un breve primo passaggio:

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 

Inoltre i tuoi dati di test tuo Itemid 4 deve essere cambiato a ovest.

1

una leggera modifica del vostro query originale:

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

Solo per il gusto di farlo, un modo di fare senza di analisi.

La soluzione di Jeffrey aveva bisogno di un DISTINCT dovuto alla duplicazione di areas. La tabella allitems è in realtà una tabella di intersezione tra currentitems e una tabella putativa areas. Nella seguente query questo è rappresentato dalla vista in linea ai. C'è un'altra vista in linea tot che ci fornisce il numero totale di record in allitems. Questo conteggio deve essere incluso nella clausola GROUP BY, in quanto non è un proiettore aggregante.

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> 

Non so se questo approccio potrebbe funzionare meglio rispetto alla soluzione di Jeffrey: è molto probabilmente si esibirà peggio (la query di analisi ha certamente meno coerente ottiene). È interessante semplicemente perché mette in evidenza le questioni in modo più chiaro.

+1

Tuttavia, grazie per il vostro contributo. Oggi non ho avuto il tempo, ma domani metterò alla prova tutte le grandi risposte! – Liao

Problemi correlati