ORACLE中用于两个varchar的“less than”是什么?

3

我有一个作业问题:

Find the celebs that have been in relationship with the same celeb. 
The result should be (celeb1, celeb2, celeb3) triples, 
meaning that celeb1 and celeb2 have been in relationship with celeb3.

现在,表“Relationships”具有celeb1和celeb2字段,其值为VARCHAR。

我的解决方案是:

  CREATE VIEW Celeb1Rels AS
SELECT celeb1 AS c1, celeb2 AS c2 FROM relationships;

CREATE VIEW Celeb2Rels AS
SELECT celeb1 AS c2, celeb2 AS c3 FROM relationships;

SELECT * FROM Celeb1Rels NATURAL JOIN Celeb2Rels;

它很好地运作。但是,讲师发布了他的解决方案,他有:

SELECT X.celeb1, Y.celeb1, X.celeb2
FROM Relationships X, Relationships Y
WHERE X.celeb2=Y.celeb2 AND X.celeb1<Y.celeb1;

我不明白为什么他在使用X.celeb1 < Y.celeb1。虽然它可以正常工作并给出正确的输出,但我认为"<"符号只用于比较数字?

有人能解释一下在这个例子中"<"的作用吗?以及当比较VARCHARS时它是如何行为的?


1
“唉”;现在老师们为了让人们感兴趣,也要这样做吗?为什么是名人?他们不能选择科学家或其他有用的人群吗……(这绝不是对你的问题的评论 - 只是对你的老师或更可能是他们的上司的评论)。 - Ben
它是一个更大的数据库的一部分,其中包括电影、专辑、名人关系、名人敌人等等。我想这样做是为了方便查询,比如“一起出演电影但被认为是敌人的名人”。 - user1411893
2
@Ben 因为科学家没有名人那么轻浮? :) - Vincent Malgrat
2
我希望你也注意到了别名的使用 - 这样在同一查询中多次引用相同的表,而无需引入视图。 - Damien_The_Unbeliever
3个回答

3

这是为了避免重复的关系。例如,有两个假想的关系:celeb1和celeb2之间的关系,以及celeb1和celeb3之间的关系,你需要得到结果。

celeb2, celeb3, celeb1

您需要第二个不等运算符,以确保表格不会在相同的关系上连接(即 celeb1 和 Celeb2 连接回到 celeb1 和 celeb2)。如果您使用您的教练查询并修改它,所以不是使用<而是使用不等于<>,您将得到以下结果:

celeb2, celeb3, celeb1
celeb3, celeb2, celeb1

但是这些行显示了同样的内容,只是按不同的顺序,> 不等运算符只是确保第二列总是一个名称在第一列之后的字母表顺序。

因此,总结一下,对于 varchar 类型,> 运算符按字母表顺序排序,所以 'a' < 'b''abc' > 'aaa' 等。


我需要担心解决方案中的重复吗?(使用自然连接)我已经在提供的示例数据库上运行了两个查询,它们都输出相同的结果。 - user1411893
仍然有使用旧的连接语法的好理由,至少在使用Oracle时是这样。 ANSI 92连接可能会导致次优执行计划。例如,http://jonathanlewis.wordpress.com/2012/07/16/ansi-outer-2/ - APC
当比较您发布的两个查询时,我得到了不同的结果。SQL Fiddle,但为了演示,我使用了<>而不是<来执行一个查询,以显示重复项。 - GarethD
@APC 很有趣,我已经从我的答案中删除了对 ANSI 89 连接的引用,因为似乎有充分的理由使用它们。 - GarethD
这是一个很好的观点。我通常更喜欢ANSI语法,特别是对于外连接,所以最让人恼火的是那些连接似乎最容易出现性能问题。 - APC

2

我猜想你想要排除重复的记录,例如:

如果在这个表中有 (A,B)(B,C) ,那么如果查询中没有 AND X.celeb1<Y.celeb1 ,我们将得到:

(A,B,C)(B,C,A)。添加此条件后,我们只输出一条记录 (A,B,C),因为 A < C


请在审查标签维基时更加仔细。你刚才通过了两个显然剽窃维基百科文本且没有注明出处的 维基 编辑。谢谢! - LittleBobbyTables - Au Revoir

1
讲师的解决方案生成三元组,其中CELEB2存在两个关系。 WHERE子句的这一部分...
X.celeb1<Y.celeb1

...确保您仅获取三位不同名人的行(即避免将同一记录与自身匹配),并且每个三元组仅获取一行。

小于号的工作方式与您想象的完全相同,它按字母顺序排序。 因此,'ANDY GARCIA' < 'ANDY KAUFMAN'为真。

需要注意的事项:

  • 它使用ASCII值,因此区分大小写。这意味着'andy garcia' < 'ANDY KAUFMAN'为假。
  • 数字也会按字母顺序排序,因此'11' < '2'为真。

"我对这个排序问题一无所知"

可以通过设置NLS_SORT参数使Oracle不区分大小写地排序。但是,这并不会改变比较方式;为了改变比较方式,我们需要将NLS_COMP参数更改为LINGUISTIC。这些不是默认行为,因为有太多的代码可能依赖于区分大小写的排序。了解更多信息


虽然与您的问题无关,但作为一个SQL-Server背景的人,我对这个排序问题一无所知。有趣的是(至少对我来说),在SQL Fiddle上支持的5个DBMS中,只有Oracle和SQLite表现出了关于大小写比较的行为。 示例: Postgresql, Oracle, SQL-Server, MySQL, SQLite - GarethD
1
@GarethD 在Oracle中的行为取决于NLS_SORTNLS_COMP会话参数(SQLFiddle)。 - Vincent Malgrat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接