mysql 使用“group by”和“having”子句的查询结果为空[重复]

rm5edbpk  于 2023-05-28  发布在  Mysql
关注(0)|答案(1)|浏览(323)

此问题已在此处有答案

Selecting from two tables with inner join and limit [duplicate](5个答案)
2天前关闭。
我有两张table:osn

+----+---------------------------------+--------+
| id | decimal_num      | eri          | devices|
+----+---------------------------------+--------+
|  1 | AD2S80AUD        | AD2S80AUD    | 419    |
|  2 | AD2S99           | AD2S99       | 419    |
|  3 | F2K_14pin        | 14pin        | F2K    |
+----+---------------------------------+--------+

osn_check

+----+--------+------------+------------+-------+------------+------+---------+
| id | osn_id | check_date | check_type | works | conclusion | fio  | comment |
+----+--------+------------+------------+-------+------------+------+---------+
|  2 |      1 | 2022-04-29 |          1 |       | NULL       | NULL | NULL    |
|  4 |      1 | 2023-05-24 |          0 | NULL  | NULL       | NULL | NULL    |
+----+--------+------------+------------+-------+------------+------+---------+

我需要从osnosn_check中选择字段,其中osn_check.check_date是每个组的最大值。我执行这个查询:

select decimal_num, eri, check_date, 
  concat(date_format(check_date, '%d.%m.%Y'), ' - ', 
  date_format(date_add(check_date, interval 1 year), '%d.%m.%Y')) 
from osn join osn_check on osn_check.osn_id=osn.id 
group by osn.id 
having check_date=max(check_date);

结果为空。我想要的结果是这样的:

AD2S80AUD | AD2S80AUD | 2023-05-24 | 24.05.2023 - 24.05.2024

我该怎么做?

ru9i0ody

ru9i0ody1#

基本上,你需要的是过滤而不是聚合。按照您最初尝试的精神,我们可以使用相关子查询来返回每个项目的最新日期,因此:

select o.*, oc.check_date, oc.check_type
from osn o
inner join osn_check oc on oc.osn_id = o.id
where oc.check_date = (
    select max(oc1.check_date)
    from osn_check oc1
    where oc1.osn_id = o.id
)

更现代的方法是使用row_number()(MySQL >= 8.0):

select o.*, oc.check_date, oc.check_type
from osn o
inner join (
    select oc.*,
        row_number() over(partition by osn_id order by check_date desc) rn
    from osn_check oc
) oc on oc.osn_id = o.id
where oc.rn = 1

如果检查表中有很多行,而引用表中有很少的行,那么横向连接可能会更有效(需要MySQL >= 8.0.14):

select o.*, oc.check_date, oc.check_type
from osn o
cross join lateral (
    select oc.*
    from osn_check oc
    where oc.osn_id = o.id
    order by check_date desc limit 1
) oc

为了提高性能,考虑osn_check(osn_id, check_date desc)上的索引,这样横向子查询可以运行得更快。

相关问题