Supposons que j'ai trois tables: user
, group
et xref
, une table qui leur donne un RI plusieurs-à-plusieurs.Comment puis-je vérifier une certaine valeur dans toutes les lignes agrégées?
je pourrais vouloir voir comment les groupes chaque utilisateur appartient à:
select
user.user_id,
user.user_name,
count(*) as group_count
from
user
inner join xref on user.user_id = xref.user_id
inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name
Tout va bien jusqu'à présent. Mais, si je veux des informations supplémentaires? Je signale, et je veux savoir si chaque utilisateur est un développeur ou un gestionnaire de contenu. Maintenant, un ressort anti-modèle:
select
user.user_id,
user.user_name,
count(*) as group_count,
max(case group.group_name when 'Developers' then 'Y' else null end)
as is_dev
max(case group.group_name when 'Content Management' then 'Y' else null end)
as is_cm
from
user
inner join xref on user.user_id = xref.user_id
inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name
Cela fonctionne, et produit les résultats escomptés, mais il se sent très mal. Ce que je veux à demander Oracle est la suivante:
« Pour chaque utilisateur, montrez-moi combien de groupes ils sont en outre, pour tous les noms de groupe par utilisateur, me montrer si « développeurs » est l'un des. les valeurs."
Ce que je suis en fait demander est ceci:.
« Pour chaque utilisateur, montrez-moi combien de groupes ils sont en outre, pour tous les noms de groupe par utilisateur, montrez-moi la valeur la plus élevée produite par cette expression
case
. "
La raison pour laquelle c'est un anti-modèle est que je suis essentiellement compter sur le fait que Y
arrive à « bulle » ci-dessus null
lors de l'évaluation avec max()
. Si quelqu'un voulait copier ou augmenter cette requête, il pourrait facilement oublier l'anti-pattern et changer accidentellement les valeurs de retour en quelque chose qui n'utilise pas la même coïncidence non intuitive.
Au fond, la requête que je voudrais pouvoir écrire est la suivante:
select
user.user_id,
user.user_name,
count(*) as group_count,
any(group.group_name, 'Developers', 'Y', null) as is_dev,
any(group.group_name, 'Content Management', 'Y', null) as is_cm
from
user
inner join xref on user.user_id = xref.user_id
inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name
J'ai tamiser autour des options, et il semble qu'il y ait quelques potentiels:
first_value
pourrait travail, mais je ne peux pas comprendre comment limiter la fenêtre correspondantepartition
aux bonnes lignes.- fonctions analytiques avec une clause
over
pourrait fonctionner, mais je ne veulent s'effondrer les colonnes je regroupement par, il ne semble pas être un ajustement parfait. De manière exaspérante, il semble y avoir une fonctionany
documentée here, mais elle n'existe que dans un mystérieux dialecte appelé Oracle OLAP DML, que je ne pense pas pouvoir accéder en utilisant uniquement SQL sur 10g. Mais, il semble faire exactement ce que je veux.
C'est tout ce que j'ai. Des idées?
Je reconnais qu'il y a deux idées très simples, "Do it in code" ou "Do it in PL/SQL", mais c'est de la triche.:-)
peut appartenir à l'utilisateur à la fois les développeurs et les gestionnaires de contenu? est-ce la raison pour laquelle vous avez besoin de deux colonnes distinctes? –
Au lieu de mettre [SQL] dans le titre, je me fierais simplement à la balise «sql». –
@be ici maintenant- Oui, c'est pourquoi. –