【问题标题】:ORDER BY in WHERE EXIST query works incorrectlyWHERE EXIST 查询中的 ORDER BY 工作不正确
【发布时间】:2019-01-20 21:49:49
【问题描述】:

ORDER BY 不适用于存在的地方

我有 ORM 生成的 SQL,但它对数据的排序不正确

SELECT * FROM `users`
WHERE (
      EXISTS
(
  SELECT *
  FROM `passports`
  WHERE `users`.`id` = `passports`.`user_id`
  AND DATE_ADD(
       birth_date,
        INTERVAL YEAR(CURDATE())-YEAR(birth_date) + IF(DAYOFYEAR(CURDATE()) 
                                               > DAYOFYEAR(birth_date),1,0)
        YEAR)
     BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
  ORDER BY DATE_ADD(
     birth_date,
            INTERVAL YEAR(CURDATE())-YEAR(birth_date)
                     + IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birth_date),1,0)
            YEAR
       );
)

ORDER BY 不起作用 但子查询排序正确

    SELECT *
    FROM  passports
    WHERE  DATE_ADD(
        birth_date,
               INTERVAL YEAR(CURDATE())-YEAR(birth_date)
                     + IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birth_date),1,0)
               YEAR
          )

         BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
  ORDER BY DATE_ADD(
            birth_date,
            INTERVAL YEAR(CURDATE())-YEAR(birth_date)
                     + IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birth_date),1,0)
            YEAR
       );

我的代码有什么问题,如何让它工作

我得到一个未排序的用户数组(第一个查询),但是他们的护照的排序数组按最早的生日排序(子查询),我希望根据子查询规则输出排序的用户数组。

【问题讨论】:

  • 能否展示users和passports的表结构? birth_date 是 users 还是 passports 的列?
  • birth_date 是护照用户列:|id|name|surname,护照:|id|user_id|birth_date|

标签: mysql sql


【解决方案1】:

这是因为您在错误的地方下订单。在子查询中,系统对行进行排序,但是在外部查询中,它们没有得到任何顺序(在 SQL 中,即使它们是有序的,SELECT 也不会按该顺序返回信息。您需要订购如果你想要一个特定的订单)。您应该通过以下方式取出订单:

SELECT * 
FROM `users`
WHERE EXISTS
        (SELECT *
         FROM `passports`
         WHERE `users`.`id` = `passports`.`user_id`
               AND DATE_ADD(birth_date,
               INTERVAL YEAR(CURDATE())-YEAR(birth_date) + IF(DAYOFYEAR(CURDATE()) 
                                                   > DAYOFYEAR(birth_date),1,0)
               YEAR)
         BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)    
         )
ORDER BY DATE_ADD(birth_date,
                INTERVAL YEAR(CURDATE())-YEAR(birth_date)
                         + IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birth_date),1,0)
                YEAR)

编辑

正如你所说,它没有找到 birth_date 列,因为它在 passports 表中。我会将您的所有查询更改为使用内部联接而不是 EXISTS:

SELECT * 
FROM `users`
inner join `passports` on `users`.`id` = `passports`.`user_id`
WHERE DATE_ADD(birth_date,
               INTERVAL YEAR(CURDATE())-YEAR(birth_date) + IF(DAYOFYEAR(CURDATE()) 
                                                   > DAYOFYEAR(birth_date),1,0)
               YEAR)
         BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
 ORDER BY DATE_ADD(birth_date,
                INTERVAL YEAR(CURDATE())-YEAR(birth_date)
                         + IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birth_date),1,0)
                YEAR)

如果您不需要所有列,则在 SELECT * 中,您必须将 * 更改为所需列的名称(users.id, passports.birth_date 等)

【讨论】:

    【解决方案2】:

    主要问题是为什么在 EXISTS 中需要 order by 子句? ORM 肯定会生成错误的 SQL。最好用您的 ORM 代码打开新问题,以便解决问题。

    您不能期望您的输出数据在这种情况下被排序。子查询在里面排序,不在主查询上。

    简单示例

    select * from tb 
    where exists (
      select x from tb2
      order by x
    );
    

    仅对带有 tb2 的子查询进行排序,但由于它用于 EXISTS 子句,因此对输出没有影响

    【讨论】:

    • 你说得对,最好打开关于 Eloquent ORM 的新问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 2018-12-21
    • 1970-01-01
    • 2021-12-18
    • 2021-07-16
    相关资源
    最近更新 更多