MYSQL-FK存在和不存在时的SubSelect

时间:2018-10-30 16:10:30

标签: mysql sql subquery

情况概述

当前问题是有关从两个表表A(物料)表B(物料修订)中选择值的问题。但是,表A的PK可能或可能不存在于表B中。当它不存在时,此问题中描述的查询将不会返回表A的值,但应。所以基本上这是发生了什么:

仅当B.id中存在A.id时,该查询才返回值,而实际上,当A.id还不存在于B.id中时,我需要它从A返回值。

问题:

假设有两个表。表材料和表材料修订。 请注意,PK idMaterial MaterialRevision 中的FK。

当前“模拟”表 enter image description here

查询目标

  

Obs:请记住,这两个表是实数的简化   表。

对于每种材料,打印材料变量和MaterialRevision的最后(MAX)RevisionDate。如果没有RevisionDate,请在“上次修订日期”上打印空白(“”)。

发生了什么事

对于每种材料,打印材料变量和MaterialRevision的最后(MAX)RevisionDate。如果没有物料修订,则不打印物料(SKIP)。

当前代码

SELECT 
    Material.idMaterial,
    Material.nextRevisionDate,
    Material.obsolete,
    lastRevisionDate
FROM Material,

 (SELECT MaterialRevision.idMaterial, max(MaterialRevision.revisionDate) as "revisionDate" from MaterialRevision  
    GROUP BY  MaterialRevision.idMaterial
 ) AS Revision

 WHERE (Material.idMaterial = Revision.idMaterial AND Material.obsolete = 0)

用于达到此问题中所述状态的参考和链接

Why is MAX() 100 times slower than ORDER BY ... LIMIT 1?

MySQL get last date records from multiple

MySQL - How to SELECT based on value of another SELECT

MySQL Query Select where id does not exist in the JOIN table

  

PS 我希望这个问题能正确理解,因为我花了很多时间来构建它。我在stackoverflow和之后研究了很多   几次失败的尝试,我别无选择,只能寻求帮助。

3 个答案:

答案 0 :(得分:1)

您应该使用JOIN

SELECT m.idMaterial, m.nextRevisionDate, mr.revisionDate AS "lastRevisionDate"
FROM Material m
LEFT JOIN MaterialRevision AS mr ON mr.idMaterial = m.idMaterial AND mr.revisionDate = (
    SELECT MAX(ch.revisionDate) from MaterialRevision ch
    WHERE mr.idMaterial = ch.idMaterial)
WHERE m.obsolete = 0

HereINNER JOINLEFT JOINRIGHT JOIN的解释。 (如果您经常在查询中跨表,就会爱上它们)

由于m.obsolete将始终为真,因此我在SELECT子句中将其省略了

答案 1 :(得分:1)

您应该使用左外部连接,而不要使用叉积。

您要查询的应该是这样的:

SELECT idMaterial, nextRevisionableDate, obsolete, 
revisionDate AS lastRevisionDate
FROM Material
LEFT OUTER JOIN MaterialRevision AS mr On 
Material.idMaterial = MaterialRevision.id
AND mr.revisionDate = (SELECT MAX(ch.revisionDate) from MaterialRevision ch 
WHERE mr.idMaterial = ch.idMaterial)
WHERE obsolete = 0;

Here,您可以找到有关联接类型的一些文档。

答案 2 :(得分:1)

借助以上答复和本文中引用的链接,我能够提出以下解决方案

SELECT m.idMaterial, m.nextRevisionDate, mr.revisionDate AS "lastRevisionDate"
FROM Material m
LEFT JOIN MaterialRevision AS mr ON mr.idMaterial = m.idMaterial AND

mr.revisionDate = (SELECT MAX(ch.revisionDate) from MaterialRevision ch WHERE 
                   mr.idMaterial = ch.idMaterial)

WHERE m.obsolete = 0

参考

Left Join on MAX(DATE)