具有相关子查询的Vanilla SQL在T-SQL中工作,在PL / SQL中失败

时间:2010-02-15 22:25:29

标签: sql sql-server oracle tsql plsql

我想在T-SQL(SQL Server 2000/2005)和PL / SQL(Oracle 10g)中使用基本相同的查询。虽然它不是微不足道的,但它是合理的vanilla代码,但它在SQL Server中工作但在Oracle中失败了。我的目标是为特定字段的每个唯一大写/小写组合生成行数,省略只有一个这样的组合的任何字段值。例如,此示例输出表示令牌“两个单词”出现在大写/小写的四种不同组合中,最常用的是全大写版本(121个这样的行)。

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

提醒一下,SQL Server默认情况下不区分大小写,因此COLLATE子句允许我区分大小写地处理它。另一方面,Oracle不需要按摩,因为它区分大小写。

此查询在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

此查询在Oracle中失败;它无法识别外部引用,抱怨它使用“无效标识符”:

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

那么Oracle PL / SQL是否有解决方法?

2010.02.16更新

在对我的完整数据集进行测试后,我接受了Gary的回答。他删除了相关的子查询以获得更紧凑的解决方案,这很好,但我仍然很好奇为什么相关的子查询尝试失败,如果有人碰巧对此有所了解......

1 个答案:

答案 0 :(得分:2)

我认为你可以逃脱

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;

经过测试:

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;