我想知道是否有人可以帮助我提高对 SQL 中 JOIN 的理解。[如果这对问题很重要,我特别考虑 MSSQLServer。]
取3个表 A,B [ A 与 B 的关系由某个 A.AId 表示] ,C [ B 与 C 的关系由某个 B.BId 表示]
如果我写一个查询,例如
SELECT *
FROM A JOIN B
ON A.AId = B.AId
一切都好,我很喜欢这样。
当表 C (或其他一些 D,E,... . 被添加时会发生什么)
在这种情况下
SELECT *
FROM A JOIN B
ON A.AId = B.AId
JOIN C ON C.BId = B.BId
C 连接到什么?-是那个 B 表(和其中的值)吗? 或者是其他临时结果集,是 C 表所连接到的 A + B 连接的结果?
[这意味着 B 表中的所有值不一定都在基于 A,B 的连接条件的临时结果集 A + B 中]
我之所以问这个问题,是因为我试图理解自己在以下方面看到的行为:
Tables
Account (AccountId, AccountBalanceDate, OpeningBalanceId, ClosingBalanceId)
Balance (BalanceId)
BalanceToken (BalanceId, TokenAmount)
Where:
Account->Opening, and Closing Balances are NULLABLE
(may have opening balance, closing balance, or none)
Balance->BalanceToken is 1:m - a balance could consist of many tokens
从概念上讲,一个日期的期末余额,就是明天的期初余额
如果我试图找到一个账户的所有期初和期末余额的列表
我可能会做一些
SELECT AccountId
, AccountBalanceDate
, Sum (openingBalanceAmounts.TokenAmount) AS OpeningBalance
, Sum (closingBalanceAmounts.TokenAmount) AS ClosingBalance
FROM Account A
LEFT JOIN BALANCE OpeningBal
ON A.OpeningBalanceId = OpeningBal.BalanceId
LEFT JOIN BALANCE ClosingBal
ON A.ClosingBalanceId = ClosingBal.BalanceId
LEFT JOIN BalanceToken openingBalanceAmounts
ON openingBalanceAmounts.BalanceId = OpeningBal.BalanceId
LEFT JOIN BalanceToken closingBalanceAmounts
ON closingBalanceAmounts.BalanceId = ClosingBal.BalanceId
GROUP BY AccountId, AccountBalanceDate
事情按照我预期的那样工作,直到最后一个 JOIN 带来结束余额标记——在结果中出现重复项。
[我可以用一个独特的方法来解决问题-但是我试图理解为什么正在发生的事情正在发生]
有人告诉我,这个问题是因为 Balance 和 BalanceToken 之间的关系是1: m-当我引入最后一个 JOIN 时,我得到了重复的内容,因为第3个 JOIN 已经多次引入了 balanceid 到(我假设)临时结果集中。
我知道示例表不符合好的数据库设计
我为这篇文章道歉,谢谢你的启发:)
编辑回应马克的问题
从概念上讲,一个账户不应该有重复的 BalanceToken (每个 AccountingDate)-我认为问题出现是因为1 Account/AccountingDate 结算余额是第二天的账户开户余额-所以当自我加入 Balance 时,BalanceToken 多次得到开户余额和结算余额,我认为 BalanceId (BalanceId)被多次加入“结果组合”。如果它有助于澄清第二个示例,那么可以把它看作是每日对账——因此是左连接——可能没有计算给定帐户/会计日期组合的期初(和/或)期末余额。