2009-06-10 5 views
2

sur Oracle 9i, pourquoi les éléments suivants produisent le résultat 'abc'Pourquoi l'ajout de count (*) à une instruction select force-t-il une ligne à exister dans une sous-requête?

select 'abc ' || (select txt from 
    (select 'xyz' as txt from dual where 1=2)) 
from dual 

alors que ce produit 'abc xyz': nombre

select 'abc ' || (select txt from 
    (select count(*), 'xyz' as txt from dual where 1=2)) 
from dual 

Pourquoi ajouter (*) au résultat de sous-requête comportement différent? Est-ce que le prédicat where 1=2 exclut tout résultat dans la sous-requête?

Répondre

15
select count(*) from dual where 1=2 

renvoie 0. C'est-à-dire, une ligne avec la valeur zéro.

+0

Tout à fait raison ... ce problème est apparu dans une requête beaucoup plus complexe où il était obscurci par un autre comportement. J'ai finalement réalisé l'erreur - le développeur original avait vraiment besoin d'utiliser count (*) over() - la fonction analytique renvoie correctement NULL - ce que le développeur voulait vraiment dans ce cas. – LBushkin

4

Il retourne le nombre de tout dans la sous-requête, qui est 0 correctement. L'utilisation de fonctions d'agrégat se comporte toujours (et correctement) de cette façon et fait partie du standard SQL.

0

count retournera toujours une valeur numérique, 0 ou un entier positif, de sorte que vous aurez toujours une ligne dans votre jeu de résultats.

Notez que les fonctions d'agrégation pourraient retourner NULL

0

Comprendre comment fonctionnent les fonctions d'agrégation dans SQL est essentielle pour l'écriture de requêtes correctes. Lorsque vous ajoutez une fonction d'agrégat (comme sum, avg, min, max, count) à une requête, vous demandez à la base de données d'effectuer une opération de groupe sur un ensemble de résultats. La plupart des agrégats, comme min et max, renvoient null lorsqu'ils sont présentés avec un jeu de lignes vide sur lequel opérer. L'exception à ceci est count() - (correctement) renvoie 0 lorsqu'il est présenté avec un ou plusieurs ensembles vides.

Cette question est née de l'analyse d'une requête beaucoup plus complexe - une avec plusieurs expressions de sous-requêtes dans la clause select. Il s'avère que l'ajout de count (*) dans l'expression select a provoqué quelques dégâts dans les résultats - car il a commencé à renvoyer une valeur où aucun n'était prévu.

Ce que le développeur voulait vraiment, était un cas où count(*) produirait null. Le moyen le plus simple d'y parvenir est l'utilisation de l'analyse dans Oracle. La requête peut être écrit pour utiliser l'équivalent de comptage analytique: count(*) over()

select 'abc ' || (select txt from 
    (select count(*) over(), 'xyz' as txt from dual where 1=2)) 
from dual 
0
(select 'xyz' as txt from dual where 1=2)) 

Cette sous-requête ne renvoie aucun RANGS.

(select count(*), 'xyz' as txt from dual where 1=2)) 

Ce rendement 1 sous_requête rangées TOUS LES TEMPS.

C'est la raison du comportement différent.

Questions connexes