mariadb 如何SQL只选择最近从相关表

wi3ka0sx  于 2023-08-05  发布在  其他
关注(0)|答案(3)|浏览(128)

我有一个请求表,我想从中选择所有内容,我有一个相关的positionReports表,我想只选择最近的报告。
下面的SQL做我想要的,只要只有一个位置报告,但只要有更多,我明白SQL没有我想要的想法.但我不知道该怎么说。

SELECT
r.id mission_id,
report.Timestamp as reportTimestamp,
report.Latitude as reportLat,
report.Longitude as reportLng,
FROM Requests r
LEFT JOIN PositionReports report ON r.id = report.RequestId

字符串

  • 更新-
    在这个MySQL JOIN the most recent row only?的指导下,我设法获取了最近的一个,但是一个新的问题是,我只能获取实际有位置报告的任务。
WHERE report.Id = (
        SELECT MAX(Id)
        FROM PositionReports
        WHERE RequestId = r.Id
    )";


是否有一种方法来检索所有这样的报告表中没有一个条目以及?尝试了外部连接,但没有区别...
它是一个MySQL数据库(测试环境是MariaDB,但生产环境是MySQL(DigitalOcean))。
当你建议预聚合时,这是否意味着我的目标是在一个SQL查询中无法实现?
样本数据--
假设RequestsTable包含两个条目,id为178和179。
| 其他数据| otherdata |
| --| ------------ |
| lorem....| lorem.... |
| ipsum....| ipsum.... |
其中只有179在positionReports表中具有匹配的行。
PositionReports表包含
| 请求ID|时间戳|纬度|经度| Longitude |
| --|--|--|--| ------------ |
| 一百七十九|123456700|五十六点五|十一点九| 11.9 |
| 一百七十九|电话:123456789|五十七点零|12.0| 12.0 |
所需的输出(查询应检索两者)。理想情况下,选择Timestamp中值最高的positionReport,但是根据Id排序也适用于此实现,因为我在接受报告时强制使用了时间顺序。
| 时间戳|纬度|经度| Longitude |
| --|--|--| ------------ |
| ||||
| 电话:123456789|五十七点零|12.0| 12.0 |

kx1ctssn

kx1ctssn1#

我想我至少让它工作感谢这个Return all data from 1st Table, and only 1 data from 2nd Table if exist
我不确定这个解决方案的效率有多高(或者我应该说是占用资源)。

SELECT
        r.id as id,
        reports.Timestamp as reportTimestamp,
        reports.Latitude as reportLat,
        reports.Longitude as reportLng,
        FROM Requests r
        LEFT JOIN 
        
        (SELECT 
          c.* 
        FROM
          PositionReports c 
          LEFT JOIN PositionReports d 
            ON c.RequestId = d.RequestId 
            AND c.Timestamp < d.Timestamp 
        WHERE d.RequestId IS NULL) reports
        
        ON r.id = reports.RequestId

字符串

jfgube3f

jfgube3f2#

没有关于资源消耗的声明-另一种方法,使用RANK窗口函数:

SELECT
  r.id as id,
  reports.Timestamp as reportTimestamp,
  reports.Latitude as reportLat,
  reports.Longitude as reportLng
FROM RequestsTable r
LEFT JOIN (
  SELECT
    *,
    RANK() OVER (PARTITION BY RequestId ORDER BY Timestamp DESC) as rnk
  FROM PositionReports
  ) reports
  on reports.RequestId = r.id
  and reports.rnk = 1
;

字符串
在行动中看到它:DB Fiddle的数据。
如果需要调整/进一步详细说明,请予以说明。

tkqqtvp1

tkqqtvp13#

是否有一种方法来检索所有这样的报告表中没有一个条目以及?
您的代码的问题在于您正在使用where子句进行过滤-因此这将驱逐left join中不匹配的记录。您可以将过滤移动到join的on子句,如下所示:

select
    r.id mission_id,
    pr.Timestamp as reportTimestamp,
    pr.Latitude as reportLat,
    pr.Longitude as reportLng
from Requests r
left join PositionReports pr 
    on  pr.RequestId = r.id
    and pr.id = ( select max(pr1.id) from PositionReports pr1 where pr1.RequestId = r.Id)

字符串
现在我们可以看到,第一个连接条件似乎是多余的,因为第二个条件覆盖了它;这应该足够了:

select
    r.id mission_id,
    pr.Timestamp as reportTimestamp,
    pr.Latitude as reportLat,
    pr.Longitude as reportLng
from Requests r
left join PositionReports pr 
    on pr.id = ( select max(pr1.id) from PositionReports pr1 where pr1.RequestId = r.Id)


最后:如果你正在运行MySQL 8.0.13或更高版本,这看起来是一个非常好的横向连接点:

select r.id mission_id,
    pr.Timestamp as reportTimestamp,
    pr.Latitude as reportLat,
    pr.Longitude as reportLng
from Requests r
left join lateral (
    select pr.*
    from PositionReports pr 
    where pr.RequestId = r.Id
    order by id desc limit 1
) pr on 1


子查询与外部查询关联,并直接返回您要查找的记录;对于PositionReports(RequestId, id desc)上的索引,这应该是一个有效的解决方案。

相关问题