2010-02-15 3 views
2

Je voudrais utiliser essentiellement la même requête dans les deux T-SQL (SQL Server 2000/2005) et PL/SQL (Oracle 10g). Bien que ce ne soit pas trivial, c'est un code raisonnablement vanille, mais cela fonctionne dans SQL Server mais échoue dans Oracle. Mon but est de générer un nombre de rangées pour chaque combinaison majuscule/minuscule unique d'un champ particulier, en omettant les valeurs de champs où il n'y a qu'une seule combinaison de ce type. Cet exemple de sortie indique par exemple que le mot "deux mots" apparaît dans quatre combinaisons différentes majuscules/minuscules, l'utilisation la plus répandue étant la version majuscule (121 lignes).Vanilla SQL avec sous-requête corrélée fonctionne dans T-SQL, échoue dans PL/SQL

 
    alias  rows affected 
    phrase   25 
    Phrase   3 
    Two words  12 
    Two Words   9 
    TWO words   3 
    TWO WORDS  121 

Pour rappel, SQL Server est insensible à la casse par défaut si la clause COLLATE me permet de travailler avec elle sensible à la casse. Oracle, d'autre part, n'a pas besoin de masser car il est sensible à la casse.

Cette requête fonctionne très bien dans T-SQL:

select 
    description COLLATE SQL_Latin1_General_CP1_CS_AS as alias, 
    count(*) as "Rows Affected" 
from dbo.svcs t1 (nolock) 
where (
    select count(upper(alias)) as "Variation Count" 
    from 
    (-- list of unique spellings for each alias 
     select 
      description COLLATE SQL_Latin1_General_CP1_CS_AS as alias, 
      count(*) as count 
     from dbo.svcs (nolock) 
     where description = t1.description 
     group by description COLLATE SQL_Latin1_General_CP1_CS_AS 
    ) combos 
    group by upper(alias) 
    having count(upper(alias)) > 1 
) > 1 
group by description COLLATE SQL_Latin1_General_CP1_CS_AS 
order by description COLLATE SQL_Latin1_General_CP1_CS_AS 

Cette requête échoue dans Oracle; il ne reconnaît pas la référence externe, se plaignant qu'il utilise un « identifiant non valide »:

select alias, count(*) as "Rows Affected" 
from dev1.svcs t1 
where (
    select count(upper(alias)) as "Variation Count" 
    from 
    (-- list of unique spellings for each alias 
     select alias, count(*) as count 
     from dev1.svcs 
     where upper(alias) = upper(t1.alias)  -- <<<<< Does not like outer reference to 't1.alias' here 
     group by alias 
    ) combos 
    group by upper(alias) 
    having count(upper(alias)) > 1 
) > 1 
group by alias 
order by alias 

Ainsi est-il une solution pour Oracle PL/SQL?

2010.02.16 Mise à jour

Après avoir testé sur mon jeu de données complet, j'ai accepté la réponse de Gary. Il a éliminé la sous-requête corrélée pour obtenir une solution plus compacte, ce qui est génial, mais je suis toujours curieux de savoir pourquoi la tentative de sous-requête corrigée échoue, si quelqu'un pense à ça ...

+0

Oracle SQL ne gère que des alias un niveau profond. Je ne peux pas voir cela documenté d'une recherche rapide, mais je crains que c'est juste comme ça. (Ce n'est pas lié à PL/SQL btw - J'ai pris la liberté de supprimer cette balise.) –

Répondre

2

Je pense que vous pouvez vous en sortir

select alias, upper(alias), count(*) cnt_alias 
from svcs m 
where upper(alias) in 
    (select upper(alias) up_a 
    from svcs 
    group by upper(alias) 
    having count(distinct alias) > 1) 
group by alias 
order by upper(alias), count(*) desc, alias; 

Testé avec:

create table svcs (id number, alias varchar2(10)); 

insert into svcs select level, 'phrase' from dual connect by level <= 25; 
insert into svcs select level, 'Phrase' from dual connect by level <= 3; 
insert into svcs select level, 'Two words' from dual connect by level <= 12; 
insert into svcs select level, 'Two Words' from dual connect by level <= 9; 
insert into svcs select level, 'TWO words' from dual connect by level <= 3; 
insert into svcs select level, 'TWO WORDS' from dual connect by level <= 121; 
insert into svcs select level, 'Only' from dual connect by level <= 121; 
+0

Gary: Votre requête Oracle fonctionne avec succès sur mon ensemble de données complet - merci! Pour être complet, je migrées votre algorithme de retour vers SQL Server ainsi: sélectionnez Description COLLATE SQL_Latin1_General_CP1_CS_AS alias, supérieure (description), count (*) comme "lignes affectées" de dbo.svcs nous (nolock) où description en (sélectionner la description de dbo.svcs (nolock) groupe par une description ayant comptage (la description distinct ASSEMBLER SQL_Latin1_General_CP1_CS_AS)> 1) groupe par la description ASSEMBLER SQL_Latin1_General_CP1_CS_AS, description commande par la description ASSEMBLER SQL_Latin1_General_CP1_CS_AS –