我想在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的回答。他删除了相关的子查询以获得更紧凑的解决方案,这很好,但我仍然很好奇为什么相关的子查询尝试失败,如果有人碰巧对此有所了解......
答案 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;