为什么这个查询的结果加倍?
当表 FI_CurrentReceiptData 只有 2 行时,我有以下查询,该查询返回 4 个结果。额外的行是完全重复的。我可以使用 DISTINCT
来修复,但我的理解是这是不好的做法,我会更好地找到并纠正错误(这是正确的吗?)。
为什么这个查询的结果加倍?
所有变量都在存储过程中的其他位置声明,并且此查询确实返回所需的字段。
SELECT ( (Select Max(ReceiptNumber)
from Avanti_InventoryReceipts) + CR.Seq ),
CR.ItemNumber,
Convert(char(8), GETDATE(), 112),
PONum,
'FL-INV',
PH.POVendor,
0,
0,
'O',
CR.QtyOrdered,
QtyReceivedToday,
QtyReceivedToday,
Case @closePO
When 'N' Then Case
When ( QtyOrdered - QtyReceivedToday ) < 0 Then 0
Else ( QtyOrdered - QtyReceivedToday )
End
When 'Y' Then 0
Else 0
End,
PD.TransCost * QtyReceivedToday,
IH.PriceWholeSale,
IH.CostLast,
QtyReceivedToday,
0,
'',
PODetailDescription /* , .... More columns...*/
FROM FI_CurrentReceiptData CR
LEFT JOIN Avanti_PODetails PD
ON CR.PONum = PD.PONumber
LEFT JOIN Avanti_POHeader PH
ON CR.PONum = PH.PONumber
LEFT JOIN Avanti_InventoryHeader IH
ON CR.ItemNumber = IH.ItemNumber
新的 WHERE 子句解决方案:
FROM FI_CurrentReceiptData CR
inner JOIN Avanti_PODetails PD ON CR.PONum = PD.PONumber AND CR.ItemNumber = PD.TransItem AND CR.QtyOrdered = PD.TransQty
left JOIN Avanti_POHeader PH ON PD.PONumber = PH.PONumber
left JOIN Avanti_InventoryHeader IH ON CR.ItemNumber = IH.ItemNumber
I have the following query which is returning 4 results when the table FI_CurrentReceiptData only has 2 rows. The extra rows are exact duplicates. I can use DISTINCT
to fix, but my understanding is that this is bad practice and I would do better to find and correct the error (IS THIS CORRECT?).
Why is this query doubling the results?
All variables are declared elsewhere in a stored procedure and this query does return the needed fields.
SELECT ( (Select Max(ReceiptNumber)
from Avanti_InventoryReceipts) + CR.Seq ),
CR.ItemNumber,
Convert(char(8), GETDATE(), 112),
PONum,
'FL-INV',
PH.POVendor,
0,
0,
'O',
CR.QtyOrdered,
QtyReceivedToday,
QtyReceivedToday,
Case @closePO
When 'N' Then Case
When ( QtyOrdered - QtyReceivedToday ) < 0 Then 0
Else ( QtyOrdered - QtyReceivedToday )
End
When 'Y' Then 0
Else 0
End,
PD.TransCost * QtyReceivedToday,
IH.PriceWholeSale,
IH.CostLast,
QtyReceivedToday,
0,
'',
PODetailDescription /* , .... More columns...*/
FROM FI_CurrentReceiptData CR
LEFT JOIN Avanti_PODetails PD
ON CR.PONum = PD.PONumber
LEFT JOIN Avanti_POHeader PH
ON CR.PONum = PH.PONumber
LEFT JOIN Avanti_InventoryHeader IH
ON CR.ItemNumber = IH.ItemNumber
NEW WHERE CLAUSE SOLUTION:
FROM FI_CurrentReceiptData CR
inner JOIN Avanti_PODetails PD ON CR.PONum = PD.PONumber AND CR.ItemNumber = PD.TransItem AND CR.QtyOrdered = PD.TransQty
left JOIN Avanti_POHeader PH ON PD.PONumber = PH.PONumber
left JOIN Avanti_InventoryHeader IH ON CR.ItemNumber = IH.ItemNumber
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
通常,当您将左连接串在一起时,您必须继续连接“左”表 - 这不是规则,但它是很好的做法,这样您就不会错过连接。在你的左连接字符串中,它包括 4 个表,并且你只将第一个表连接到所有三个表:
你没有将 PD 连接到 IH 到 PH,而是基本上将 CR 表连接到所有三个表 - 所以本质上它是在做PD、PH 和 IH 之间的交叉连接(基于它们匹配的任何字段)。我假设 POheader 和 POdetails 有一些匹配的字段......并且我假设它是表之间的一对多关系? (基于名称)。所以那里需要一些限制...
编辑:
所以你可以尝试,(基于字段关系)
编辑2:
好的,所以根据你所说的,CR 有 2 行,CR 有一个 1-to-与PH是1对多的关系,PH与PD是一对多的关系。并且CR与IH也具有1对t的关系。在这种情况下,假设您具有引用完整性,您可以将联接更改为:
让我们退一步 - 这将根据 PD 和 PH 行是否匹配来限制它们,即使它们不匹配也不会得到空值't(这就是左连接的作用)。
但现在,如果 CR 中有 2 行,并且每个 PONumber 在 POHeader 中有 2 行,并且每个 POheader 在 POdetails 中有超过 1 行,那么肯定会有重复项。确实没有办法避免这种情况。原因是这样的:
CR TABLE
PH TABLE
PD TABLE
...如果将 CR 表连接到 PH 表,您将只得到两行。如果将 PH 联接到 PD 表,则将有 4 行。如果您加入所有 3 行,那么您还将获得 4 行。连接的本质是跨所有表,因此当您从 CR 表转到 PH 时,它会得到 2 行的结果集...然后该结果集连接到 PD,有 4 行。如果您可以确认您的数据是这样的,那么您得到的结果集就是正确的。
Usually when you string left joins together, you have to keep joining the 'left' table - its not a rule but its good practice so you don't miss joins. In your string of left joins, it includes 4 tables, and you only joined the first one to all three:
You aren't joining PD to IH to PH, but basically left joining the CR table to all three - so essentially it is doing a cross join between PD and PH and IH (based on whatever fields they are matching on). I assume POheader and POdetails have some fields they match on.... and I assume its a one to many relationship between the tables? (based on the names). So there needs to be some restriction there...
EDIT:
So can you try, (based on the field relationships)
EDIT 2:
Ok, so by what you are saying, CR has 2 rows, and CR has a 1-to-1 relationship to PH, and PH has a 1-to-many relationship to PD. And CR also has a 1-to-t relationship to IH. In which case, assuming you have referencial integrity, you can change your joins to this:
Lets take a step back - this will restrict the PD and PH rows based on whether they match or not, and won't get nulls even if they don't (which is what left joins do).
But now, if you have 2 rows in CR, and each of the PONumbers have 2 rows in POHeader, and each POheader has more than 1 row in POdetails, then you will definitely have duplicates. There is really no way to avoid this. The reason is this:
CR TABLE
PH TABLE
PD TABLE
...if you join the CR table to PH table, you will get only two rows. If you join PH to PD tables, then you will 4 rows. If you join all 3, then you will also get 4 rows. The nature of the join is across all the table, so when you go from the CR table to PH, it gets a resultset of 2 rows...and then that resultset gets join to PD, and there 4 rows. If you can confirm that your data is as such, then the resultset you are getting is correct.
由于您正在执行 LEFT JOINS,因此您将为所有匹配记录返回 1 行。因此,您要加入的表之一返回的行数超过 1 行。
尝试暂时更改查询以将其他表主键添加到列列表中,您应该能够快速判断哪个表返回的行数超过 1 行。
Since you're doing LEFT JOINS, you will get 1 row returned for all matching records. So one of the tables you are joining to is returning more than 1 row.
Try temporarily changing your query to add the other tables primary key to the column list and you should be able to quickly tell which table is returning more than 1 row.
连接的表之一具有多个匹配行。
我不能确定是哪一个,但如果我是你,我就会开始寻找
在 Avanti_PODetails 表中。两张收据中的任何一张是否有多个匹配记录?
One of the joined tables has more than one matching row.
I cannot say for certain which one, but if I were you I'd start looking
at the Avanti_PODetails table. Does it have more than one matching record for any of the two receipts?