【问题标题】:Unknown column from within double nested derived table in JOIN statementJOIN 语句中双嵌套派生表中的未知列
【发布时间】:2014-07-23 10:08:14
【问题描述】:

在我的数据库中,有两种类型的图像:挑战和答案。它们都有 lat/lng 位置列。在此查询中,我希望通过 INNER JOIN 选择用户最近创建的挑战或答案

(这背后的业务逻辑:我们基本上想获得一个用户列表,其中包括用户最近的已知位置,这是由他们最近的挑战决定的答案 - 以最近的为准。如果用户没有最近的已知位置,则不应将其包含在此列表中。)

我收到[Err] 1054 - Unknown column 'U.Id' in 'where clause':

SELECT
    U.Id,
    U.TotalPoints,
    LastImage.Lat,
    LastImage.Lng
FROM User U
INNER JOIN
(
    SELECT Lat, Lng FROM
    (
        (SELECT Lat, Lng, CreatedOn FROM AnswerImage WHERE UserId = U.Id ORDER BY Id DESC LIMIT 1)
        UNION ALL
        (SELECT Lat, Lng, CreatedOn FROM ChallengeImage WHERE UserId = U.Id ORDER BY Id DESC LIMIT 1)
    ) LastImages ORDER BY CreatedOn DESC LIMIT 1
) LastImage
WHERE U.Type = 1 AND U.Status = 2
ORDER BY TotalPoints DESC;

我似乎无法从派生的“LastImages”表(或任何合适的术语)中引用用户表(别名 U)。

有人可以帮忙吗?我尝试了其他方法,但没有一个能满足我的所有要求:

  1. 只有在用户至少有 1 个挑战或 1 个答案(因此是 UNION)时才会返回一行
  2. 最新的(由 ChallengeImage.CreatedOn 和 AnswerImage.CreatedOn 确定)图像将用于连接

谢谢!

【问题讨论】:

    标签: mysql sql nested-queries derived-table


    【解决方案1】:
    SELECT u.id,
           u.TotalPoints,
           IF(IFNULL(a.CreatedOn, '1900-01-01') > IFNULL(c.CreatedOn, '1900-01-01'), a.Lat, c.Lat) AS Lat,
           IF(IFNULL(a.CreatedOn, '1900-01-01') > IFNULL(c.CreatedOn, '1900-01-01'), a.Lng, c.Lng) AS Lng
    FROM User AS u
    LEFT JOIN
        (SELECT UserId, Lat, Lng, CreatedOn
         FROM AnswerImage AS a
         JOIN (SELECT UserId, MAX(CreatedOn) AS CreatedOn
               FROM AnswerImage
               GROUP BY UserId) AS amax
         USING (UserId, CreatedOn)) AS a
        ON u.id = a.UserId
    LEFT JOIN
        (SELECT UserId, Lat, Lng, CreatedOn
         FROM ChallengeImage AS c
         JOIN (SELECT UserId, MAX(CreatedOn) AS CreatedOn
               FROM ChallengeImage
               GROUP BY UserId) AS cmax
         USING (UserId, CreatedOn)) AS c
        ON u.id = c.UserId
    WHERE U.Type = 1 AND U.Status = 2
        AND (a.Lat IS NOT NULL OR c.Lat IS NOT NULL)
    ORDER BY TotalPoints DESC;
    

    子查询是获取表中每个组的最后一行的常用方法之一,请参阅

    Retrieving the last record in each group

    然后您将他们与User 表一起离开,这样即使用户在两个表中都没有匹配项,您也会得到结果。

    【讨论】:

    • 我会试一试,现在只是尝试修复它。许多拼写错误,例如表 'b' 不存在、'ChallengeImageImage'、'ChallenImage' 等。=P
    • 这似乎给了我没有挑战也没有答案的用户的记录。
    • 您可以在末尾使用HAVING Lat IS NOT NULL 过滤掉那些。
    • 与添加到 WHERE 子句相比如何:WHERE U.Type = 1 AND U.Status = 2 AND (a.Lat IS NOT NULL OR c.Lat IS NOT NULL)
    • HAVING 子句如何满足我的要求 #1?我们有两个 LEFT JOIN,所以这是否仍会导致返回既没有最新挑战也没有最新答案的用户?
    【解决方案2】:

    您的userid = u.id 确实在错误的位置。既然您要拉一条记录,那么最后一行中order by 的原因是什么? 请试一试。未经测试:(

    select u.id, u.totalpoints, a.lat, a.lng
    from user u
    join (
        select userid, lat, lng, createdon
        from AnswerImage
        union all
        select userid, lat, lng, createdon
        from ChallengeImage) a on a.userid = u.id
    where u.type = 1 and u.status = 2
    order by a.createdon desc
    limit 1;
    

    【讨论】:

    • 我不是只提取一条记录,而是提取具有最后一个已知位置的所有用户的列表 - “最后一个已知位置”被定义为他们最近的 lat/lng 信息挑战或回答,以最近的为准。
    • 啊,我明白了,Barmar 的结果可能就是您想要的结果。
    猜你喜欢
    • 2016-05-27
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    相关资源
    最近更新 更多