【问题标题】:Oracle Join Using + derived columnOracle Join Using + 派生列
【发布时间】:2018-05-21 07:51:30
【问题描述】:

我正在优化可读性。 SQL join 'using' 语法在语法上比适用的 'on' 更简洁。理想情况下我想写:

select *, 
  col1 + col2 as derviedCol 
from table1 join table2 using (joinCol1, joinCol2)

但是,在使用“使用”语法 (ORA-00904) 时,oracle(我怀疑其他数据库)不会让您使用表标识符,所以我能做的下一个最好的事情是:

select t.*, 
  col1 + col2 as derviedCol 
from (
  select * from table1 join table2 using (joinCol1, joinCol2)
) t

select t1.*, t2.*, 
  col1 + col2 as derviedCol 
from table1 t1 
join table2 t2 on 
  t1.joinCol1 = t2.joinCol1 
  and t1.joinCol2 = t2.joinCol2

有人可以建议更简洁的语法吗?

【问题讨论】:

标签: sql oracle


【解决方案1】:

您可以分配别名并使用它们来限定列计算;例如

select co.shortname || '.' || ci.shortname as mycol
from countries co
join cities ci using (ISOCODE);

或者简单地通过它们各自的表名来限定列;例如

select countries.shortname || '.' || cities.shortname as mycol
from countries
join cities using (ISOCODE);

不确定这是否符合您对“不那么冗长”的定义

【讨论】:

  • 不幸的是,它是 * 我所追求的,而不仅仅是派生列。
  • 好吧,那你碰壁了:psoug.org/oraerror/ORA-25154.htm 最终你可能会做出这样的决定:using 不值得麻烦,因为它施加的所有限制。
【解决方案2】:

我质疑开场白,并认为“使用语法”不太“干净”。即使有要通过的通用名称进行连接,并且自然连接“隐藏”了“重复的列名”,派生表仍然可以包含相同名称的列(例如,下面看到的“shortname”在两者中都存在但不存在连接的一部分)。

此外,如果“使用连接”指定了两个列,则返回两个列,即使它们具有相同的列名。

对于连接语法中的一些额外字符,您可以获得更精确(和灵活)的方法,可以在任何查询中使用,而无需特殊的数据模型条件。我还认为,使用 ON 样式连接的句法一致性会导致更少的可变性,因此更容易维护。

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE COUNTRIES
    (COUNTRY varchar2(9), ISOCODE varchar2(3), SHORTNAME varchar2(4))
;

INSERT ALL 
    INTO COUNTRIES (COUNTRY, ISOCODE, SHORTNAME)
         VALUES ('Aruba', 'ABW', NULL)
    INTO COUNTRIES (COUNTRY, ISOCODE, SHORTNAME)
         VALUES ('Australia', 'AUS', 'Oz')
    INTO COUNTRIES (COUNTRY, ISOCODE, SHORTNAME)
         VALUES ('Austria', 'AUT', NULL)
SELECT * FROM dual
;

CREATE TABLE CITIES
    (ISOCODE varchar2(3), CITY varchar2(9), SHORTNAME varchar2(3))
;

INSERT ALL 
    INTO CITIES (ISOCODE, CITY, SHORTNAME)
         VALUES ('AUS', 'Melbourne', 'Mel')
SELECT * FROM dual
;

查询 1

select * from countries join cities using (ISOCODE)

Results

| ISOCODE |   COUNTRY | SHORTNAME |      CITY | SHORTNAME |
|---------|-----------|-----------|-----------|-----------|
|     AUS | Australia |        Oz | Melbourne |       Mel |

查询 2

select * from countries join cities using (ISOCODE,ISOCODE)

Results

| ISOCODE | ISOCODE |   COUNTRY | SHORTNAME |      CITY | SHORTNAME |
|---------|---------|-----------|-----------|-----------|-----------|
|     AUS |     AUS | Australia |        Oz | Melbourne |       Mel |

查询 3

select * from countries left join cities using (ISOCODE)

Results

| ISOCODE |   COUNTRY | SHORTNAME |      CITY | SHORTNAME |
|---------|-----------|-----------|-----------|-----------|
|     AUS | Australia |        Oz | Melbourne |       Mel |
|     AUT |   Austria |    (null) |    (null) |    (null) |
|     ABW |     Aruba |    (null) |    (null) |    (null) |

查询 4

select * from countries left join cities using (ISOCODE,ISOCODE)

Results

| ISOCODE | ISOCODE |   COUNTRY | SHORTNAME |      CITY | SHORTNAME |
|---------|---------|-----------|-----------|-----------|-----------|
|     AUS |     AUS | Australia |        Oz | Melbourne |       Mel |
|     AUT |     AUT |   Austria |    (null) |    (null) |    (null) |
|     ABW |     ABW |     Aruba |    (null) |    (null) |    (null) |

【讨论】:

  • 我明白你的意思,并已将我的声明修改为“语法上不那么冗长”。我可以完全控制我的数据模型,因此不会遇到您上面提到的边缘情况。 'on' 语法虽然更标准和更明确,但在加入许多列时可能会变得难以阅读。我并不是说自然连接是灵丹妙药,但在许多情况下都很方便。我只是想知道我上面的代码是否有更简洁的语法,我想避免关于哪个更好的哲学/火焰战争辩论。
  • 那么您已经回答了自己的问题。不;通过natural join 路由没有“语法上不那么冗长”的方式。我不确定我是否会将我上面的评论描述为火焰,但是,我确实认为您将花费在使用自然连接上的努力并没有得到充分利用,特别是当其他不太熟悉您的方法的人能够坚持这一点时代码。
  • 开场白没有谈到“自然连接”——using() 子句明确列出了连接列,与 natural join 运算符形成对比。 from a join b using (x,y)from a natural join b 非常不同
  • @a_horse_with_no_name 好点。在心理上,我将这些东西混为一谈(作为我不使用的连接类型)。所以我做了一个小编辑。谢谢。
猜你喜欢
  • 1970-01-01
  • 2020-02-06
  • 2013-08-03
  • 2023-01-27
  • 2014-07-23
  • 2016-05-27
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
相关资源
最近更新 更多