我想知道是否有人可以帮助提高我对SQL JOIN的理解。[如果对该问题很重要,那么我正在特别考虑MS SQL Server。]
取3张表A,B [与A.AId有关的B有关的A]和C [与B.BId有关的C有关的B]
如果我撰写查询,例如
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引入期末余额令牌-我最终在结果中得到重复项。
[我可以通过DISTINCT进行修复-但我试图理解为什么发生了什么]
我被告知问题是因为Balance和BalanceToken之间的关系是1:M-并且当我引入最后一个JOIN时我得到重复,因为第三个JOIN已经多次将BalanceIds引入了(我假设)临时结果集。
我知道示例表不符合良好的数据库设计
为这篇文章道歉,谢谢您的启发:)
根据马克的问题进行编辑
从概念上讲,对于一个帐户(每个AccountingDate),BalanceToken中不应存在重复项-我认为问题是由于1个Account / AccountingDates的期末余额是第二天的帐户期初余额-因此,当我自动加入Balance时,BalanceToken多次获得期初和期末余额我认为Balances(BalanceId's)被多次引入“结果组合”中。如果有助于阐明第二个示例,则可以将其视为每日对帐-因此是左联接-对于给定的帐户/会计日期组合,可能尚未计算期初(和/或)期末余额。