【问题标题】:SQL inner join from field defined table?来自字段定义表的 SQL 内连接?
【发布时间】:2010-04-14 22:57:02
【问题描述】:

目前,我总共有 6 个表是这个问题的一部分。主表 tableA 包含其他 5 个表中的所有条目共有的列。其他 5 个表的列更详细地定义了 tableA 中的条目。

例如:

TableA
ID|Name|Volume|Weight|Description
--+----+------+------+-----------
0 |T1  |0.4   |0.1   |Random text
1 |R1  |5.3   |25    |Random text

TableB
ID|Color|Shape
--+-----+------
0 |Blue |Sphere

TableC
ID|Direction|Velocity
--+---------+--------
1 |North    |3.4

(列名只是示例,不要理解它们的含义......)

表 A 中的 ID 字段对所有其他表都是唯一的(即 TableB 将具有 0,但 TableC 不会,任何其他表也不会)。

我想做的是从 TableA 中选择所有字段以及相应的(根据 ID 字段)明细表 (TableB-F)。

我目前所做但未测试的是向 TableA 添加了一个字段,因此它看起来像这样:

TableA
ID|Name|Volume|Weight|Description|Table
--+----+------+------+-----------+------
0 |T1  |0.4   |0.1   |Random text|TableB
1 |R1  |5.3   |25    |Random text|TableC

我对此有几个问题:

  1. 对 TableA 做这样的事情是否合适,因为外键在这种情况下不起作用,因为它们都需要链接到不同的表?

  2. 如果这是正确的,SQL 查询是否会像这样(ID 将由用户输入)?

    SELECT *
    FROM TableA AS a
    INNER JOIN a.Table AS t ON a.ID = ID;

  3. 有更好的方法吗?

感谢您的帮助。

【问题讨论】:

    标签: sql


    【解决方案1】:
    1. 如果说 TableA 是主表,那么所有明细表(TableB、TableC 等)都应该在 A 上具有 FK,反之则不然。

    2. 要从 TableA 中选择一条记录并从其他表中选择所有详细信息,请使用 LEFT JOIN:

      SELECT A.*, B.color,B.shape, C.direction, C.velocity
      FROM TableA A
      LEFT JOIN TableB B ON (B.id = A.id)
      LEFT JOIN TableC B ON (C.id = A.id)

    【讨论】:

    • 如果列总是被填充,内连接会很好
    【解决方案2】:

    这是处理超类型/子类型模型的常用方法。例如,Employee 和 Customer 是 Person 的子类型...

    PERSON
    
    Id|PType|Name      
    --+-----+----------
     1|EMP  |APC       
     2|CUS  |WOLF      
     3|CUS  |SUESS     
    
    EMPLOYEE
    
    Id|PType|Job      |Sal    |HireDate  |DeptNo      
    --+-----+---------+-------+----------+------
     1|EMP  |PLUMBER  |   3500|20-MAY-09 |    50   
    
    CUSTOMER
    
    Id|PType|Ref      |CreditRating   
    --+-----+---------+------------
     2|CUS  |W/10/2   |AAA    
     3|CUS  |S/10/3   |AA     
    

    子类型表上 PType 列的重复可能看起来有点奇怪。但它对于在子类型表和超类型表之间强制执行强外键很有用。 PERSON 表在(ID) 上有一个主键,在(ID,PTYPE) 上有一个唯一键。子类型对 PTYPE 有 CHECK 约束;例如在客户上它会CHECK (ptype='CUS')。这意味着子类型可以在(ID,PTYPE) 上有一个外键,这确保了 CUSTOMER 中的记录只能引用 PTYPE 为“CUS”的 PERSON 中的记录。

    至于查询,您可能想要做这样的事情来获取员工:

    select p.*
           , e.job
           , e.sal
           , e.hiredate
           , e.deptno
    from person p
         inner join employee e
         on ( p.id = e.id
              and p.ptype = e.ptype )
    /
    

    这是为了获得客户:

    select p.*
           , c.ref
           , c.creditrating
    from person p
         inner join customer c
         on ( p.id = c.id
              and p.ptype = c.ptype )
    /
    

    在连接条件中包含 PTYPE 是可选的,但它的存在可能有助于数据库优化器选择更好的执行路径。

    可以使用外连接查询所有 PERSON 记录及其子类型列...

    select p.*
           , e.job
           , e.sal
           , e.hiredate
           , e.deptno
           , c.ref
           , c.creditrating
    from person p
         left outer join employee e
         on ( p.id = e.id
              and p.ptype = e.ptype )
         left outer join customer c
         on ( p.id = c.id
              and p.ptype = c.ptype )
    /
    

    但是,这不是您应该轻易做的事情。对于五个这样的表,外部连接可能会生成非常糟糕的访问路径。单独查询的执行速度可能比单个聚合查询快得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2011-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多