Reputation: 3549
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
Upvotes: 0
Views: 1793
Reputation: 4837
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:
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
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)
FROM FI_CurrentReceiptData CR
LEFT JOIN Avanti_PODetails PD
ON CR.PONum = PD.PONumber
LEFT JOIN Avanti_POHeader PH
ON CR.PONum = PH.PONumber AND PD.PONumber = PH.PONumber
LEFT JOIN Avanti_InventoryHeader IH
ON CR.ItemNumber = IH.ItemNumber
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:
FROM FI_CurrentReceiptData CR
LEFT JOIN Avanti_POHeader PH ON CR.PONum = PD.PONumber
INNER JOIN Avanti_PODetails PD ON PH.PONumber = PD.PONUmber
LEFT JOIN Avanti_InventoryHeader IH ON CR.ItemNumber = IH.ItemNumber
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
PONum ItemNumber
--------- ----------
123 ABC
456 DEF
PH TABLE
PONumber
---------
123
456
PD TABLE
PONumber ItemNumber
--------- -----------
123 ABC
123 ABC1
456 DEF
456 DEF1
...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.
Upvotes: 3
Reputation: 11283
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.
Upvotes: 1
Reputation: 33283
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?
Upvotes: 0