查询中的 LEFT JOIN 返回比预期更多的记录

Posted

技术标签:

【中文标题】查询中的 LEFT JOIN 返回比预期更多的记录【英文标题】:LEFT JOIN in Query returning more records than desired 【发布时间】:2017-08-26 22:26:01 【问题描述】:

我正在处理一个 MS ACCESS 查询,它应该从一个主表(由 FROM 指定)中提取所有可用数据,然后通过 LEFT JOIN 加入三个额外的表。我的问题是由于一对多关系,查询返回了更多记录。

有什么方法可以在主表中每行只返回一条记录?任何帮助是极大的赞赏!!谢谢!

    SELECT tbl_Item_PO.Item, 
    tbl_ItemSKUType.SKU, 
    tbl_Item_PO.[EX-FACTORY DATE], 
    tbl_Item_PO.[QTY PER SHIPMENT],
    IIf(tbl_Item_PO.Item=Posted_Inv_Tran.Item And tbl_Item_PO.Whse=Posted_Inv_Tran.Whse And tbl_Item_PO.[ITR#]=Posted_Inv_Tran.[TRN Number],0,tbl_Item_PO.[QTY PER SHIPMENT]) AS QTY, 
    tbl_Item_PO.WHSE, tbl_WhseRegion.Region
    FROM ((tbl_Item_PO 
    LEFT JOIN tbl_ItemSKUType ON tbl_Item_PO.item = tbl_ItemSKUType.Item) 
    LEFT JOIN tbl_WhseRegion ON tbl_Item_PO.WHSE = tbl_WhseRegion.Whse) 
    LEFT JOIN Posted_Inv_Tran ON (tbl_Item_PO.[ITR#] = Posted_Inv_Tran.[TRN Number]) AND (tbl_Item_PO.Whse = Posted_Inv_Tran.Whse) AND (tbl_Item_PO.Item = Posted_Inv_Tran.Item);

我也尝试在只返回一条记录的连接语句中创建子查询,但我也无法让它工作:

    SELECT po.Item, 
    ist.SKU, 
    po.[EX-FACTORY DATE], 
    po.[QTY PER SHIPMENT],
    IIf(po.Item=itr.Item And po.Whse=itr.Whse And po.[ITR#]=itr.[TRN Number],0,po.[QTY PER SHIPMENT]) AS QTY, 
    po.WHSE, 
    wh.Region
    FROM ((tbl_Item_PO po
    LEFT JOIN (select top 1 * from tbl_ItemSKUType
             RIGHT JOIN tbl_Item_PO on tbl_ItemSKUType.Item = tbl_Item_PO.item
             WHERE tbl_Item_PO.Item = tbl_ItemSKUType.Item) 
             ist ON po.item = ist.Item)
    LEFT JOIN (select top 1 * from tbl_WhseRegion
             RIGHT JOIN tbl_Item_PO on tbl_WhseRegion.Whse = tbl_Item_PO.Whse
             WHERE tbl_Item_PO.whse = tbl_WhseRegion.Whse) 
             wh ON po.Whse = wh.Whse)
    LEFT JOIN (select top 1 * from Posted_Inv_Tran
            RIGHT JOIN tbl_Item_PO on Posted_Inv_Tran.[TRN Number] = tbl_Item_PO.[ITR#] AND Posted_Inv_Tran.Whse = tbl_Item_PO.Whse AND Posted_Inv_Tran.Item = tbl_Item_PO.Item
            WHERE (tbl_Item_PO.[ITR#] = Posted_Inv_Tran.[TRN Number]) AND (tbl_Item_PO.Whse = Posted_Inv_Tran.Whse) AND (tbl_Item_PO.Item = Posted_Inv_Tran.Item)) 
            it ON (po.[ITR#] = it.[TRN Number]) AND (po.Whse = it.Whse) AND (po.Item = it.Item);

【问题讨论】:

你可能不想要一个三左连接,你可能想要两个左连接的内连接。 Because 你并不总是在最左边的表的键上加入等于它的 FK。想一想:左连接返回内连接返回的内容以及由空值扩展的不匹配行。非 FK 键的内连接可以引入多行。但是在我回答之前,您需要给出限制条件和最好的示例数据来确认。事实上,代码总是给一个minimal reproducible example 或者一个问题是题外话。 【参考方案1】:

您可以使用group by 子句来实现。确保列出该子句中标识一行的所有字段,并且您在 select 子句中拥有的所有其他表达式/字段都使用某些聚合函数进行聚合,例如 Min()

注意:您的IIf 条件不需要检查所有这些字段,只需一个就足够了:当一个匹配时,所有将匹配:

SELECT  tbl_Item_PO.Item, 
        Min(tbl_ItemSKUType.SKU) AS SKU, 
        tbl_Item_PO.[EX-FACTORY DATE], 
        tbl_Item_PO.[QTY PER SHIPMENT],
        Min(IIf(tbl_Item_PO.Item=Posted_Inv_Tran.Item, 0,  
                                  tbl_Item_PO.[QTY PER SHIPMENT])) AS QTY, 
        tbl_Item_PO.WHSE,
        Min(tbl_WhseRegion.Region) AS Region
FROM    ((tbl_Item_PO 
LEFT JOIN tbl_ItemSKUType 
        ON tbl_Item_PO.item = tbl_ItemSKUType.Item) 
LEFT JOIN tbl_WhseRegion 
        ON tbl_Item_PO.WHSE = tbl_WhseRegion.Whse) 
LEFT JOIN Posted_Inv_Tran 
        ON (tbl_Item_PO.[ITR#] = Posted_Inv_Tran.[TRN Number]) 
        AND (tbl_Item_PO.Whse = Posted_Inv_Tran.Whse) 
        AND (tbl_Item_PO.Item = Posted_Inv_Tran.Item)
GROUP BY tbl_Item_PO.Item, 
        tbl_Item_PO.[EX-FACTORY DATE], 
        tbl_Item_PO.[QTY PER SHIPMENT],
        tbl_Item_PO.WHSE;

【讨论】:

谢谢!这可能有效。我唯一担心的是,对于连接表中具有多个匹配项的记录,QTY(数量)值会被放大。 MIN 函数会解决这个问题吗? Min 将只取一个值,即适合连接的众多值中的最小一个。但是由于当您有多个连接匹配时,该值实际上将是相同的重复值,这仅意味着:“选择该值”。如果您使用Sum 而不是Min,它炸毁。

以上是关于查询中的 LEFT JOIN 返回比预期更多的记录的主要内容,如果未能解决你的问题,请参考以下文章

join,left join,inner join的区别?

SQL语句中LEFT JOIN和RIGHT JOIN 以及INNER JOIN的区别

加入两个查询会返回比预期更多的行?

多表查询-inner join left join right joinfull join

sql之left joinright joininner join的区别

left joinright join和inner join