2010-09-29 3 views
2

Cela fonctionne:Encountering ORA-00979: pas GROUP BY expression lors de l'utilisation CASE - IN déclarations sql

SELECT (CASE 
      WHEN x = 'value' THEN 
       a.col1 
      ELSE 
       nvl(a.col1, a.col2) 
      END) 
     FROM table1 a 
    WHERE a.this = 'that' 
    GROUP BY (CASE 
       WHEN x = 'value' THEN 
       a.col1 
       ELSE 
       nvl(a.col1, a.col2) 
       END) 

Mais en essayant d'avoir la déclaration de cas faire une déclaration IN (en essayant une sql plus dynamique ici), le code suivant génère une erreur ORA-00979.

SELECT (CASE 
     WHEN x IN (SELECT me FROM here WHERE this = 'example') THEN 
      a.col1 
     ELSE 
      nvl(a.col1, a.col2) 
     END) 
    FROM table1 a 
WHERE a.this = 'that' 
GROUP BY (CASE 
      WHEN x IN (SELECT me FROM here WHERE this = 'example') THEN 
      a.col1 
      ELSE 
      nvl(a.col1, a.col2) 
      END) 

Est-il possible de faire ce travail ou d'avoir une alternative? Merci. --Jonas

Benoit: Voici un sql modifié en fonction de votre sql recréant l'erreur:

select (case when a.y IN (select 'A'||ROWNUM from dual where rownum=1) then 1 else 0 end) 
from (SELECT 'A'||ROWNUM y, 'B' x FROM DUAL CONNECT BY ROWNUM <= 3) a where x = 'B' 
group by (case when a.y IN (select 'A'||ROWNUM from dual where rownum=1) then 1 else 0 end) 
; 

Fondamentalement, ce qui ne manquait que la table FROM devrait avoir plus de valeurs et qu'un colonne a été référencée dans l'instruction CASE.

+0

Quelle version d'Oracle utilisez-vous? –

+0

Oublié d'ajouter. Nous utilisons Oracle 10g – jonasespelita

+1

Votre dernière sélection fonctionne sur Oracle 11gR2, pas sur v9. – Benoit

Répondre

2

Je ne peux pas reproduire cette erreur à la demande suivante (travail):

select (case when 'X' IN (select dummy from dual where rownum=1) then 1 else 0 end) 
from dual 
where dummy = 'X' 
group by (case when 'X' IN (select dummy from dual where rownum=1) then 1 else 0 end) 
; 

Essayez:

WITH table1_extended AS (
    SELECT a.*, CASE WHEN x IN .... END "condition" 
    FROM table1 a 
) 
SELECT b."condition" 
    FROM table1_extended b 
WHERE b.this = 'that' 
GROUP BY b."condition" 
+0

intéressant. En effet, le test de simulation fonctionne. Je vais regarder plus dans mes sélections et essayer d'avoir un sql factice plus précis. Pour l'instant un upvote pour vous mon bon monsieur. – jonasespelita

+0

J'ai oublié de dire que je l'ai testé sur un 11g Release 11.2.0.1.0 64bit AS AUSSI sur un 9.2.0.6.0. – Benoit

+0

Benoît, je mets un montage qui devrait reproduire ce que je vois. Merci, – jonasespelita

1

Y at-il une raison que vous ne pouvez pas déplacer le sous-sélection dans une jointure? A partir de votre version ajustée sur @ cas de test de Benoit que vous pourriez faire:

select case when a.y = b.z then 1 else 0 end, count(*) 
from (select 'A'||rownum y, 'B' x from dual connect by rownum <= 3) a, 
    (select 'A'||rownum z from dual where rownum=1) b 
where a.x = 'B' 
group by case when a.y = b.z then 1 else 0 end; 

Ce qui donne (en 10g):

CASEWHENA.Y=B.ZTHEN1ELSE0END COUNT(*)    
---------------------------- ---------------------- 
1       1      
0       2 

Pas tout à fait convaincu que donnera la réponse que vous voulez, mais difficile de dire que C'est tellement simplifié et ça pourrait être un point de départ.


Modifier Cela semble en effet trop simpliste. Une autre solution possible qui ressemble aussi beaucoup trop simple mais pourrait faire l'affaire est d'aborder ce de l'autre extrémité et juste faire le case dans la select une fonction d'agrégation:

SELECT MIN(CASE 
     WHEN x IN (SELECT me FROM here WHERE this = 'example') THEN 
      a.col1 
     ELSE 
      nvl(a.col1, a.col2) 
     END) 
    FROM table1 a 
WHERE a.this = 'that' 
GROUP BY (CASE 
      WHEN x IN (SELECT me FROM here WHERE this = 'example') THEN 
      a.col1 
      ELSE 
      nvl(a.col1, a.col2) 
      END) 
+0

votre code en tant que contexte, 'b' est censé être une table de configuration, nous obtiendrons donc un cartésien si nous allons déplacer le sous-ensemble dans une jointure. Oui, le code actuel est alambiqué de la logique métier. – jonasespelita

+1

@jonasespelita: Les jointures cartésiennes ne sont pas intrinsèquement mauvaises. Si votre deuxième sélection renvoie toujours une ligne, le résultat cartésien ne sera pas plus grand que le résultat de la requête que vous avez écrite et la performance devrait être presque identique. – Allan

+0

@Allan En effet. Mais puisque dans la production actuelle, la deuxième sélection renvoie plus d'une douzaine de lignes .. vous avez l'idée. :) Merci pour l'info. – jonasespelita