MySQL离开连接的问题

MySQL(5.1)中有3个表: account,bank_account_data和investment_account_data。 表格定义如下: (注意:这是一个简化版本,实际表格中有更多列,银行和投资数据具有不同的信息,这些信息对于此特定情况不需要,但需要在其他地方使用)
CREATE TABLE account
(
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  type ENUM ('INVESTMENT', 'BANK') NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE investment_account_data
(
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  account_id BIGINT UNSIGNED NOT NULL,
  as_of_date TIMESTAMP NULL DEFAULT NULL,
  total_balance NUMERIC(12, 4) NOT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (account_id) REFERENCES account (id),
  CONSTRAINT unique_per_account_and_date UNIQUE (account_id, as_of_date)
) ENGINE=InnoDB;

CREATE TABLE bank_account_data
(
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  account_id BIGINT UNSIGNED NOT NULL,
  as_of_date TIMESTAMP  NULL DEFAULT NULL,
  current_balance NUMERIC(12, 4) NOT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (account_id) REFERENCES account (id),
  CONSTRAINT unique_per_account_and_date UNIQUE (account_id, as_of_date)
) ENGINE=InnoDB;
目前我在帐户表中只有一个帐户,其中id = 1且type ='INVESTMENT' 我在investment_account_data表中有一条记录(id = 1,account_id = 1,total_balace = 15000,as_of_data ='2011-03-02 00:00:00') bank_account_data没有行。 运行以下查询(令人惊讶)不返回任何行:
SELECT A.id as account_id,
       COALESCE(BD.as_of_date, ID.as_of_date) as as_of_date,
       COALESCE(BD.current_balance, ID.total_balance) as balance
  FROM account A
       LEFT JOIN bank_account_data BD ON (BD.account_id = A.id and A.type='BANK') 
       LEFT JOIN investment_account_data ID ON (ID.account_id = A.id and A.type='INVESTMENT')
 WHERE A.id=1
但是这一行返回一行(如预期的那样):
SELECT A.id as account_id,
       COALESCE(BD.as_of_date, ID.as_of_date) as as_of_date,
       COALESCE(BD.current_balance, ID.total_balance) as balance
 FROM account A
      LEFT JOIN investment_account_data ID ON (ID.account_id = A.id and A.type='INVESTMENT')
      LEFT JOIN bank_account_data BD ON (BD.account_id = A.id and A.type='BANK') 
 WHERE A.id=1
为什么我看到这些结果的任何想法? 此外,如果我从连接中删除A.type条件,它也将返回一行。     
已邀请:
鉴于您发布的查询和数据,这正是您应该期望的输出。 在第一个查询中,第一个连接条件指定
A.type = 'BANK'
。因此,在第一个
LEFT JOIN
之后,你有一个零行的结果集,然后你再次
LEFT JOIN
。如果“左”侧为零行,则
LEFT JOIN
(或
INNER JOIN
)也将始终返回零行。 对于第二个查询,订单是相反的。因此,在第一次连接之后,您将拥有单行结果集。您现在在“左”侧有一行用于第二次连接。     
我猜想看到行为的原因是你在第一个join子句的类型字段上创建了一个过滤器,它掩盖了第二个join子句中的所有帐户。 选择所有类型为“BANK”的帐户 加入相应的银行帐户信息 从最后一个结果集中选择所有与“投资”类型匹配的帐户,即所有与“BANK”类型匹配的帐户 使用相应的投资帐户信息加入空集。 修复 执行此操作的肮脏和不好的方法是创建一组不同的连接条件
SELECT A.id as account_id,
       COALESCE(BD.as_of_date, ID.as_of_date) as as_of_date,
       COALESCE(BD.current_balance, ID.total_balance) as balance
 FROM account A
      LEFT JOIN investment_account_data ID ON (ID.account_id = A.id)
      LEFT JOIN bank_account_data BD ON (BD.account_id = A.id) 
 WHERE 
      A.id=1
      AND ((ID.account_id is not null and A.TYPE='INVESTMENT') 
          OR
           (BD.account_id is not null and A.TYPE = 'BANK'))
必须使用OR之类的东西让我觉得数据库架构有些臭。您可以使用更适合的UNION来做同样的事情。 在我看来,您的意图是该帐户可以是银行帐户或投资帐户。数据库模式目前并未强制执行此问题中详细说明需要此类查询的情况。帐户表的目的似乎是为所有帐户ID提供空间。它可以用序列替换。我也不确定您是否需要根据当前定义为银行账户和投资账户设置不同的表格。您可以对两个表执行相同的操作,一个包含帐户信息,另一个包含每个日期的帐户余额。     
问题在于左连接的处理方式和A.type条件。
UNION
将是您尝试做的更合适的操作员。
SELECT account_id, as_of_date, current_balance as balance
       FROM bank_account_data
UNION
SELECT account_id, as_of_date, total_balance as balanceas
       FROM investment_account_data
(如果需要帐户表中的其他信息,请插入联接) 此外,您可能希望重新考虑数据库布局,如果它们确实具有相同的属性且仅在类型上有所不同,则将三者合并为一个。     

要回复问题请先登录注册