【问题标题】:Using sub-query to SELECT MAX value along with LEFT JOIN使用子查询与 LEFT JOIN 一起选择 MAX 值
【发布时间】:2013-09-25 00:23:57
【问题描述】:

我有一个获取搜索结果的查询,效果很好。

查询成功示例:

 SELECT
    individuals.individual_id,
    individuals.unique_id,
    TIMESTAMPDIFF(YEAR,individuals.day_of_birth,CURDATE()) AS age,
    individuals_dynamics.id,
    individuals_achievements.degree
  FROM
    individuals as individuals
  LEFT JOIN
    individuals_dynamics AS individuals_dynamics ON individuals.unique_id = individuals_dynamics.individual_id
  LEFT JOIN
    individuals_achievements AS individuals_achievements ON individuals.unique_id = individuals_achievements.individual_id
  WHERE
    $uuid_access_status $display_type $detailed_search_query
  ORDER BY 
    $search_sort $search_order

从现在开始,每个人在individuals_achievements 中都有不止一条记录,这是我想要获取 MAX 值(最新 id)的地方。

我尝试了许多不同的查询,但总是收到错误在非对象上调用成员函数 rowCount()。

我理解这个错误的含义,但我不知道我在哪里犯了这个错误以及一般是什么错误。

我不成功的尝试示例:

  SELECT
    individuals.individual_id,
    individuals.unique_id,
    TIMESTAMPDIFF(YEAR,individuals.day_of_birth,CURDATE()) AS age,
    individuals_dynamics.id,
    individuals_achievements.degree
  FROM
    individuals as individuals
  LEFT JOIN
    individuals_dynamics AS individuals_dynamics ON individuals.unique_id = individuals_dynamics.individual_id
  INNER JOIN
  (
       SELECT
            degree, MAX(id) AS latest_record
       FROM
            individuals_achievements
       GROUP BY
            latest_record
  ) individuals_achievements AS individuals_achievements ON individuals.unique_id = individuals_achievements.individual_id
  WHERE
    $uuid_access_status $display_type $detailed_search_query
  ORDER BY 
    $search_sort $search_order

我在这里缺少什么?请问有什么帮助吗?

【问题讨论】:

    标签: mysql sql join subquery


    【解决方案1】:

    如果在处理查询时出现错误,PDO::query 将返回 FALSE,并将 rowCount 作为成员函数应用到 FALSE 将导致您看到的错误。

    检查您的查询是否有语法错误并解析PDO 会返回给您的任何错误消息。

    【讨论】:

    • 谢谢你,Quassnoi!就像我说的,我理解这个错误的含义。它总是返回与我查询不是对象的东西相同的错误,因为我想到了不正确的子查询!
    【解决方案2】:
    INNER JOIN
      (
           SELECT
                degree, MAX(id) AS latest_record,individual_id
           FROM
                individuals_achievements
           GROUP BY
                latest_record
      ) individuals_achievements AS individuals_achievements_1 ON individuals.unique_id = individuals_achievements_1.individual_id
    

    应该是

    INNER JOIN (SELECT blah) AS something ON individuals.unique_id=something.individual_id

    【讨论】:

    • 和我的例子不一样吗?有什么区别?只是使用其他名称?不幸的是,它不起作用!返回相同的错误!不过谢谢你,试一试!
    【解决方案3】:

    您必须在INNER JOIN 中选择individual_id,因为您在ON 子句中使用的那部分,并且您只选择了degree, MAX(id) AS latest_record 并尝试加入individual_id,这在新生成的未定义内联表

    individuals_achievements AS individuals_achievements 
    ON individuals.unique_id = individuals_achievements.individual_id
    

    试试这个

    SELECT
        individuals.individual_id,
        individuals.unique_id,
        TIMESTAMPDIFF(YEAR,individuals.day_of_birth,CURDATE()) AS age,
        individuals_dynamics.id,
        individuals_achievements.degree
      FROM
        individuals as individuals
      LEFT JOIN
        individuals_dynamics AS individuals_dynamics ON individuals.unique_id = individuals_dynamics.individual_id
      INNER JOIN
      (
           SELECT
                degree, MAX(id) AS latest_record,individual_id
           FROM
                individuals_achievements
           GROUP BY
                latest_record
      ) individuals_achievements AS individuals_achievements_1 ON individuals.unique_id = individuals_achievements_1.individual_id
      WHERE
        $uuid_access_status $display_type $detailed_search_query
      ORDER BY 
        $search_sort $search_order
    

    确保您在表 individuals_achievements 中有一个列 individual_id

    【讨论】:

    • 不,我的朋友,事实并非如此!我试过了!不过,谢谢你的帮助,dianuj!
    • 我只指出了错误:),戈登也指出了,但更有帮助的是戈登的回答,欢迎您
    【解决方案4】:

    这是您的from 子句:

      FROM
        individuals as individuals
      LEFT JOIN
        individuals_dynamics AS individuals_dynamics ON individuals.unique_id = individuals_dynamics.individual_id
      INNER JOIN
      (
           SELECT
                degree, MAX(id) AS latest_record
           FROM
                individuals_achievements
           GROUP BY
                latest_record
      ) individuals_achievements AS individuals_achievements ON individuals.unique_id = individuals_achievements.individual_id;
    

    我至少可以发现三个问题。第一个是individuals_achievements AS individuals_achievements;第二个是对不在子查询中的individuals_achievements.individual_id 的引用。第三个是group by latest_record

      FROM individuals LEFT JOIN
           individuals_dynamics
           ON individuals.unique_id = individuals_dynamics.individual_id LEFT JOIN
           individuals_achievements
           ON individuals.unique_id = individuals_achievements.individual_id JOIN
           (SELECT ia.individual_id, MAX(ia.id) AS latest_record
            FROM individuals_achievements ia
            GROUP BY ia.individual_id
           ) iamax
           ON individuals.unique_id = iamax.individual_id and
              individuals_achievements.id = iamax.latest_record
    

    这会添加一个额外的子查询,带有最新记录的 id。

    顺便说一句,表别名与表名同名是多余的。这只会使查询变得混乱。此外,对别名使用表缩写是个好主意,例如 ia 代表 individuals_achievements。因为这个答案只关注from 子句,所以我没有做出改变。

    【讨论】:

    • 谢谢你,戈登!你的答案听起来很正确!您忘记了查询中的degree,主要部分!我会试着告诉你更多关于我得到了什么!
    • @IliaRostovtsev 。 . .您仍然可以从individuals_achievements 表中提取学位。子查询的唯一用途是查找最新记录。
    • 你是对的!!刚刚让它按预期的方式工作!感谢您的回答和解释!
    • Gordon,我可以看到你在你的例子中没有使用ASFROM individuals_achievements ia 如果你使用它,是不是也一样,有点简写?你不喜欢individuals_achievements AS individuals_achievements 的哪些方面?也许是冗余?不比速写更易读吗? ;)
    • @IliaRostovtsev 。 . .作为偏好,我使用as 作为列别名,而将它们用于表别名。从视觉上看,它可以帮助我发现列何时被重命名。数据库对此不一致。 Oracle 不允许as 用于表别名; MS Access 似乎需要它。
    【解决方案5】:

    首先,您并没有真正在 SQL 中使用 AS 关键字来使您的查询更具可读性,这会有所帮助。我想知道WHERE 子句的(php?)变量中有什么。

    另外,您的子查询没有返回字段individual_id,但您尝试加入它。我想你可能想要这个:

    SELECT
      ind.individual_id,
      ind.unique_id,
      TIMESTAMPDIFF(YEAR,ind.day_of_birth,CURDATE()) AS age,
      ind_dyn.id,
      ind_ach.degree
    FROM
      individuals as ind
    LEFT JOIN
      individuals_dynamics AS ind_dyn ON ind.unique_id = ind_dyn.individual_id
    INNER JOIN
      individuals_achievements AS ind_ach 
         ON ind_ach.individual_id = ind.unique_id
        AND ind_ach.id =
        (
          SELECT MAX(id) FROM individuals_achievements
          WHERE individuals_achievements.individual_id = ind.unique_id
        )
    WHERE
      $uuid_access_status $display_type $detailed_search_query
    ORDER BY 
      $search_sort $search_order
    

    【讨论】:

    • 谢谢你,funkwurm!老实说,对我来说,常规表名更具可读性!为什么我要使用简写来命名它?我无法为您提供子查询,它太庞大了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    • 2015-07-24
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多