mySQL

时间:2016-04-01 14:17:25

标签: mysql

  

有没有办法做一个条件 JOIN,以便它根据父表字段返回其中一个子表的列?

TL; DR:

我正在尝试在mySQL中实现Class Table Inheritance (aka Table Per Type Inheritance)。 AFAIK不是开箱即用的,因此需要进行一些黑客攻击才能打开它。

考虑以下SQL架构。

Customer

我想做什么:

  • 获取CustomerIndividual IF 的记录 CustomerOrganization IF 它们存在。
  • 我为idCustomer条款传递WHERE

理想的结果集:

  • 如果Customer.typeIndividual = TRUE

Result with <code>Customer</code> & <code>CustomerIndividual</code> columns combined

  • 如果Customer.typeOrganization = TRUE

Result with <code>Customer</code> & <code>CustomerOrganization</code> columns combined

重要要注意,此查询将始终返回仅1条记录,因此列号将是可变的。

我目前正在做的事情:

  SELECT *
  FROM Customer
  LEFT JOIN CustomerIndividual
  ON Customer.idCustomer = CustomerIndividual.idCustomer
  LEFT JOIN CustomerOrganization
  ON Customer.idCustomer = CustomerOrganization.idCustomer
  WHERE Customer.idCustomer = ?

但当然这是:

  • 返回CustomerCustomerIndividual&amp;的所有CustomerOrganization
  • 返回重复的列,例如idCustomer列,显示在所有3个表格中。
  • 生成CustomerOrganization列,即使客户个人,反之亦然。

我的问题:

有没有办法执行条件 JOIN,以便根据Customer.typeIndividual/Customer.typeOrganization字段返回其中一个子表的 列?< / p>

注意:

  • 在任何给定时间,Customer.typeIndividualCustomer.typeOrganization都可以是TRUE。不是两个在同一时间。 Customer可以是IndividualOrganization

  • 如果事情变得更简单,我就可以重组。我感觉我使用的Customer.typeIndividual OR Customer.typeOrganization分化标志在某种程度上是多余的,也许我可以通过查看Customer是个人/组织来推断子表已满。

  • 我知道我可以在应用程序级别上进行完全不同的查询但是,我正在寻找一个银弹。

1 个答案:

答案 0 :(得分:2)

也许你可以这样做,但我不推荐它。

SELECT
  Customer.*,
  COALESCE(CI.firstName, CO.organizationName) AS firstName_or_organizationName,
  COALESCE(CI.maidenName, CO.registrationNo) AS maidenNamee_or_registrationNo,
  lastName --  here you get last_name or NULL if is an organization
  FROM Customer C
  LEFT JOIN CustomerIndividual  CI
         ON Customer.idCustomer = CustomerIndividual.idCustomer
  LEFT JOIN CustomerOrganization CO
         ON Customer.idCustomer = CustomerOrganization.idCustomer
  WHERE Customer.idCustomer = ?

或使用商店程序

DELIMITER ;;
CREATE DEFINER=CURRENT_USER PROCEDURE stored_procedure_name(IN CustomerID INT)
BEGIN
    DECLARE boolTypeIndividual INT;

    SELECT Customer.typeIndividual into boolTypeIndividual
    FROM Customer
    WHERE Customer.idCustomer = CustomerID 

    IF (boolTypeIndividual) THEN
            SELECT C.*,   CI.*
            FROM Customer C
            LEFT JOIN CustomerIndividual  CI
                   ON Customer.idCustomer = CustomerIndividual.idCustomer
            WHERE Customer.idCustomer = CustomerID 
    ELSE
            SELECT C.*,   CO.*
            FROM Customer C
            LEFT JOIN CustomerOrganization CO
                   ON Customer.idCustomer = CustomerOrganization.idCustomer
            WHERE Customer.idCustomer = CustomerID 
    END IF
END;;
DELIMITER ;