【问题标题】:MYSQL - SubSelect when FK does and doesnt existsMYSQL - 当DO存在和不存在时SubSelect
【发布时间】:2019-04-03 17:51:41
【问题描述】:

情况概览

当前的问题是关于从两个表table A(material)table B(MaterialRevision)中选择值的问题。但是,表 A 的 PK 在表 B 中可能存在也可能不存在。当它不存在时,此问题中描述的查询将不会返回表 A 的值,但它应该。所以基本上这就是发生的事情:

查询只在 B.id 中存在 A.id 时返回值,实际上,当 B.id 中不存在 A.id 时,我需要它从 A 中返回值。

问题:

假设有两个表。表 Material 和 Table Material Revision。 请注意,PK idMaterialMaterialRevision 中的 FK。

当前的“模拟”表

查询目标

Obs:记住这两张表是真实的简化版 表格。

对于每个材质,打印材质变量和来自 MaterialRevision 的最后一个(MAX)RevisionDate。如果没有 RevisionDate,则为“最后修订日期”打印 BLANK ("")。

发生了什么错误

对于每个材质,打印材质变量和来自 MaterialRevision 的最后一个(MAX)RevisionDate。如果 Material 没有 Revision,则不打印 Material (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和之后研究了很多 几次尝试都失败了,我别无选择,只能寻求帮助。

【问题讨论】:

    标签: mysql sql subquery


    【解决方案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
    

    Here 解释了 INNER JOINLEFT JOINRIGHT JOIN 是什么。 (如果您经常在查询中交叉表,您会喜欢它们)

    由于m.obsolete 总是正确的,我在SELECT 子句中省略了它

    【讨论】:

    • 感谢您的回复。但此查询仅返回具有 MAX 修订日期的材料。实际上我需要返回everyMaterial 并且只返回带有MAX revisionDate 的版本。
    • 奇怪。它应该返回所有过时的Material 至少有一个MaterialRevision...
    • 它必须返回也没有材料修订的材料
    • 好的,所以您可以将INNER JOIN 替换为LEFT JOIN。我的错,我误解了你的问题。
    • 我发现了这个问题。编辑后我会将您的答案标记为正确。我将发布我的答案,以便您进行编辑。我真的很感谢你的回答。没有你,我无法解决它。非常感谢。向您致敬,先生。
    【解决方案2】:

    您应该使用左外连接而不是使用叉积。

    你的查询应该是这样的:

    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 你可以找到一些关于连接类型的文档。

    【讨论】:

    • 对不起,这只返回一个值。
    • 是的,我的错误只返回具有最高修订日期的行。
    • 我应该在连接中使用最大值,就像您在答案中所做的那样,现在我编辑我的
    猜你喜欢
    • 1970-01-01
    • 2018-09-17
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多