2009-09-25 3 views
0

je sélectionne des données agrégées et de regroupement à la date et un domaine particulier. Je veux afficher toutes les valeurs dans ce champ et un nombre de ces valeurs même s'il n'y avait pas de données correspondant à ce champ ce jour-là. Par exemple.suppression de sous-requête supplémentaire dans le tableau Oracle, en sélectionnant des valeurs

Date  MyField Count 
2009-09-25 A  2 
2009-09-25 B  0 
2009-09-24 A  1 
2009-09-24 B  1 

SQL Oracle J'ai actuellement à faire est semblable à ce qui suit:

SELECT today, 
     mytable.myfield, 
     COUNT(
     CASE WHEN fields.myfield = mytable.myfield AND 
        date >= today AND 
        date < tomorrow 
       THEN 1 
     END 
     ) 
FROM (
     SELECT TRUNC(SYSDATE) + 1 - LEVEL AS today, 
       TRUNC(SYSDATE) + 2 - LEVEL AS tomorrow 
     FROM DUAL 
     CONNECT BY LEVEL <= 30 
    ), 
    (
     /* This is the part that seems inefficient */ 
     SELECT DISTINCT myfield 
     FROM mytable 
     WHERE myfield IN ('A', 'B') 
    ) fields, 
    mytable 
GROUP BY today, mytable.myfield 
ORDER BY today DESC, mytable.myfield ASC 

Mon souci est que je sais exactement quels sont les valeurs que je veux afficher pour myfield, et il semble inefficace avez une requête SELECT qui accède à mytable. Je me demandais s'il y a une certaine façon que je pouvais faire quelque chose comme ça dans cette sous-requête:

SELECT ('A', 'B') AS myfield 
FROM DUAL 

J'utilise une ancienne version d'Oracle où les clauses WITH ne fonctionnent pas.

+0

Quelle version d'Oracle utilisez-vous? Le niveau de connexion ne fonctionne pas dans Oracle 8, donc vous utilisez Oracle 9 ou 10. Mais Oracle 9 et 10 ont la clause with, vous devriez donc pouvoir utiliser la clause with. – tuinstoel

+0

CONNECT PAR NIVEAU fonctionne vraiment, mais les clauses n'ont pas travaillé dans l'interface que je utilise pour accéder à la base de données de mon entreprise. Je ne suis pas sûr de la version d'Oracle. –

+0

Sélectionnez * à partir de la version v $ pour connaître le type de version Oracle que vous utilisez. – tuinstoel

Répondre

1

Vous auriez à les obtenir comme des lignes différentes, pas des colonnes différentes. Donc, vous vous retrouverez avec

select 'A' from dual 
union 
select 'B' from dual 

Dans ce cas, la requête doit être équivalent aussi longtemps que il y a des lignes mytable avec champs 'A' et « B ». Si jamais il n'y en a pas, votre sous-requête renverra des lignes que la sous-requête d'origine ne retournera pas.

0

Pourquoi la mise à niveau ne vous pas votre version Oracle? La clause with est ajoutée en premier à Oracle 9.2 (2002). Utilisez-vous toujours Oracle 8?

0

Vous ne disposez pas d'une jointure entre la sous-requête FIELDS et MYTABLE, de sorte que votre resultset contiendra une ligne pour chaque valeur de MYFIELD pour les trente derniers jours.

Cependant, au lieu d'ajouter que rejoindre, pourquoi ne pas abandonner la sous-requête et filtrer uniquement sur MYTABLE.MYFIELD? En outre, si vous êtes préoccupé par la performance que vous devez lié la date dans une clause WHERE, sinon vous traiter toutes les lignes de MYTABLE.

select today 
     , myfield 
     , count (case when trunc(somedate) = today then 1 end) as ab_count 
from (select trunc(sysdate) + 1 - level as today 
     from dual 
     connect by level <= 30) 
     , mytable 
where myfield in ('A', 'B') 
and somedate >= trunc(sysdate) - 30 
group by today, myfield 
order by today desc, myfield asc 
/

modifier

J'ai couru votre requête initiale et mon révisé une contre certaines données de test. Vous aurez juste à prendre ma parole que les deux resulsets étaient en fait identiques - ou essayer vous-même :)

Votre requête renvoie:

TODAY  M AB_COUNT 
----------- - ---------- 
26-SEP-2009 A   0 
26-SEP-2009 B   0 
25-SEP-2009 A   2 
25-SEP-2009 B   2 
24-SEP-2009 A   2 
24-SEP-2009 B   0 
... 
29-AUG-2009 A   1 
29-AUG-2009 B   2 
28-AUG-2009 A   1 
28-AUG-2009 B   0 

60 rows selected. 

SQL> 

Mes requête retourne:

TODAY  M AB_COUNT 
----------- - ---------- 
26-SEP-2009 A   0 
26-SEP-2009 B   0 
25-SEP-2009 A   2 
25-SEP-2009 B   2 
24-SEP-2009 A   2 
24-SEP-2009 B   0 
... 
29-AUG-2009 A   1 
29-AUG-2009 B   2 
28-AUG-2009 A   1 
28-AUG-2009 B   0 

60 rows selected. 

SQL> 
Questions connexes