【问题标题】:Non-Equi Self Join非Equi 自加入
【发布时间】:2016-10-24 06:22:07
【问题描述】:

我有以下用户表

用户

name    city
A       New York
B       Paris
C       London
D       London
E       Paris

我想使用 non equi self join 从同一个城市中选择两个用户 使得结果如下

name  name  city
B     E     Paris
C     D     London

【问题讨论】:

  • 请标记您的 DBMS。
  • 请说明您的要求(不使用equi self join)。

标签: sql oracle self-join


【解决方案1】:

“自连接”就像普通的连接 execpet,同一个表出现在连接子句的两侧。 “non-equi”意味着查找在某些列上不匹配的行。

因此,在您的情况下,您需要加入 CITY 并过滤 NAME 的差异:

select t1.name as t1_name
       , t2.name as t2_name
       , t1.city
from users t1
     join users t2
     on t2.city = t1.city
where t1.name < t2.name

注意过滤条件是less than:使用not equals会使结果集加倍。(*)

显然,此解决方案适用于 CITY 有两个条目的情况。如果有两个以上的条目,您仍然会得到多行(每个组合一个)。


(*) 有时使用!= 是可取的:如果我们正在调查数据质量问题,那么从两行返回所有列可以帮助我们了解发生了什么。

【讨论】:

    【解决方案2】:

    您也可以通过以下方式使用 cte

    WITH CITY
    AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY A.CITY ORDER BY A.CITY) RNO,A.NAME,A.CITY FROM Table1 A
    )
    
    SELECT A.NAME,B.NAME,A.CITY FROM 
    CITY A JOIN 
    CITY B
    ON 
    A.city=B.city AND A.NAME<>B.name AND A.RNO<=B.RNO
    

    【讨论】:

    • 不确定这个解决方案会给聚会带来什么,但如果你要这样做,那么按 NAME 而不是 CITY 来排序分区子句会更有意义。
    • @APC 用户需要为同一个城市选择两个用户,所以我使用了城市分区,所以对于这种情况,它得到了预期的结果。
    • 我的观点是,CTE 增加了执行成本的开销,而不会对结果集产生实质性影响。那么您认为这个查询提供了哪些优势来证明额外成本是合理的?
    • @APC 我认为像打两次物理表可能不是一个好习惯,所以我在 cte 中取得了结果并使用了它。如果我错了,请纠正我。
    • 我认为这属于“过早优化”的范畴。此外,您是否针对您的解决方案运行了解释计划?试试看,你可能会感到惊讶! ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 2017-05-29
    • 2019-11-12
    相关资源
    最近更新 更多