2

我正在重写一个由 Business Objects 生成并使用“老式”隐式连接语法的查询。该代码将一个表与自身连接在一起,并且还有一个“全局”where 子句。例如:

select   a.col1
       , b.col2
from     MYDB.TABLE a, MYDB.TABLE b
where    a.something=b.something_else
     and MYDB.TABLE.source='A'

以上是对问题的虚构说明。实际查询很长,大概要连接十张表。

我的问题:如上所述,“额外”条件是否适用于同一张表的两个实例?我认为是的,但我以前从未见过这样的代码。我正在使用 Teradata,但我认为这是一个一般的 SQL 问题。

更新: 也许我试图缩小问题的范围并不准确。这是我要修改的完整查询:

SELECT
  abs_contrct_prof.contrct_nbr_txt,
  gbs_org_LVL1.bus_pln_sgmnt_cd,
  abs_gnrc_lst_of_val_LVL1.wirls_val_1_txt
FROM
  EDWABSUSERVIEWS.abs_contrct  abs_contrct_prof,
  EDWABSUSERVIEWS.gbs_org  gbs_org_LVL1,
  EDWABSUSERVIEWS.abs_gnrc_lst_of_val  abs_gnrc_lst_of_val_LVL1,
  EDWABSUSERVIEWS.abs_contrct,
  EDWABSUSERVIEWS.gbs_sls_actv_blng_org_rltd,
  EDWABSUSERVIEWS.gbs_sls_actv_org_rltd
WHERE
  ( abs_contrct_prof.type_cd = 'PROFILE'  )
  AND  ( EDWABSUSERVIEWS.abs_contrct.type_cd = 'AGREEMENT'  )
  AND  ( abs_contrct_prof.prnt_contrct_id=EDWABSUSERVIEWS.abs_contrct.contrct_id  )
  AND  ( abs_contrct_prof.org_id=EDWABSUSERVIEWS.gbs_sls_actv_org_rltd.org_id  )
  AND  ( EDWABSUSERVIEWS.gbs_sls_actv_org_rltd.gbs_lvl_3_org_id=EDWABSUSERVIEWS.gbs_sls_actv_blng_org_rltd.gbs_lvl_3_org_id  )
  AND  ( EDWABSUSERVIEWS.gbs_sls_actv_blng_org_rltd.gbs_lvl_1_org_id = gbs_org_LVL1.org_id  )
  AND  ( gbs_org_LVL1.bus_pln_sgmnt_cd=abs_gnrc_lst_of_val_LVL1.nm_txt and abs_gnrc_lst_of_val_LVL1.actv_ind = 'Y' and abs_gnrc_lst_of_val_LVL1.type_cd ='ABS_MOBILITY_SEGMENT'  )
  AND  
  abs_contrct_prof.contrct_nbr_txt  IN  @variable('FAN')
  AND  ( EDWABSUSERVIEWS.abs_contrct.sts_cd = 'Active'  )
  AND  ( EDWABSUSERVIEWS.abs_contrct.type_cd='AGREEMENT'  )

请注意,该表EDWABSUSERVIEWS.abs_contrct在 FROM 子句中被引用两次,一次使用别名,一次不使用。是的,这个查询按书面形式工作,但我想重写它以使用显式连接语法(正如有人评论的那样)。

我对查询进行了解释,似乎“额外”条件(用于“活动”和“协议”)实际上分别应用于表的两个实例。

4

3 回答 3

4

“额外”条件是否适用于同一张表的两个实例?

不,它没有。它仅适用于表的一个实例。

另外,这样写的查询不正确,它应该(并且可能会)在大多数 SQL 实现中给出错误。您必须命名ab

select   a.col1
       , b.col2
from     MYDB.TABLE a, MYDB.TABLE b
where    a.something=b.something_else
     and a.source = 'A'                     --or:--   and b.source = 'A'
于 2012-10-18T15:36:34.760 回答
3

如果您TRANSACTION MODETERADATA优化器,则优化器会将子句中的完全限定表引用与WHERE包含 INNER JOIN 结果的假脱机文件相结合。我还不能用TRANSACTION MODEset to测试这个ANSI

例子

CREATE VOLATILE TABLE Test1
    (
        Col1 SMALLINT NOT NULL,
        col2 VARCHAR(10) NOT NULL
    )
    PRIMARY INDEX (Col1)
    ON COMMIT PRESERVE ROWS;

CREATE VOLATILE TABLE Test2
    (
        Col1 SMALLINT NOT NULL,
        col2 VARCHAR(10) NOT NULL
    )
    PRIMARY INDEX (Col1)
    ON COMMIT PRESERVE ROWS;

SELECT A.Col1
     , B.Col2
     , Test1.Col1
  FROM Test1 A
     , Test2 B
 WHERE A.Col1 = B.Col1
   AND Test1.Col1 = 1;

解释 - Teradata 模式

  1) First, we do an all-AMPs JOIN step from USER.B by way of a RowHash
     match scan with no residual conditions, which is joined to USER.A
     by way of a RowHash match scan with no residual conditions. 
     USER.B and USER.A are joined using a merge join, with a join
     condition of ("USER.A.Col1 = USER.B.Col1").  The result goes into
     Spool 2 (one-amp), which is redistributed by the hash code of (9)
     to all AMPs.  The size of Spool 2 is estimated with low confidence
     to be 1 row (15 bytes).  The estimated time for this step is 0.02
     seconds. 
  2) Next, we do a single-AMP JOIN step from Spool 2 (Last Use) by way
     of an all-rows scan, which is joined to USER.Test1 by way of the
     primary index "USER.Test1.Col1 = 1" with no residual conditions. 
     Spool 2 and USER.Test1 are joined using a product join, with a
     join condition of ("(1=1)").  The result goes into Spool 1
     (all_amps), which is built locally on that AMP.  The size of Spool
     1 is estimated with low confidence to be 1 row (22 bytes).  The
     estimated time for this step is 0.01 seconds. 
  3) Finally, we send out an END TRANSACTION step to all AMPs involved
     in processing the request.
  -> The contents of Spool 1 are sent back to the user as the result of
     statement 1.  The total estimated time is 0.03 seconds. 

更新

INSERT INTO Test1 VALUES (1,'C');
INSERT INTO Test1 VALUES (2,'D');
INSERT INTO Test2 VALUES (1, 'C1');
INSERT INTO Test2 Values (2, 'D2');

结果

Col1  Col2  Test1.Col1
----++----++----------
1     C1    1
2     D2    1

过滤条件未应用于FROM子句中的表。

于 2012-10-18T16:27:11.673 回答
2

dbms 在解析查询时所做的第一件事(就像它所做的那样)是从所有表构造函数(FROM 子句、JOIN 等)构建一个工作表。

紧接着 dbms (就像它一样)进入 WHERE 子句,并从工作表中删除所有未测试为 TRUE 的行。

因此,有效的WHERE 子句适用于工作表中的所有行。暴躁的 Joe Celko 是早期 SQL 标准委员会的成员,他经常在网上写过关于处理顺序的文章。(在该链接中搜索主题以获取Effectively materialize。)

于 2012-10-18T15:44:54.317 回答