postgresql
有A表 字段为 车辆名,日期时间,里程
如何从A表中获取车辆每10000公里时的日期时间和里程。这个里程不一定为准确10000,20000。获取其最接近10000里程差的即可。
最后输出字段为 车辆名,日期时间,里程
表头 | 表头 | 表头 |
---|---|---|
A | 2023-05-11 15:23:23 | 10001 |
A | 2023-05-30 15:33:33 | 20010 |
B | 2022-05-12 16:00:31 | 10100 |
引用gpt部分指引作答:
你可以使用 PostgreSQL 的窗口函数和数值函数来实现这个需求。以下是一个示例查询语句:
SELECT vehicle_name, datetime, mileage
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY vehicle_name ORDER BY ABS((mileage / 10000) * 10000 - mileage) ASC) AS rn
FROM A
) subquery
WHERE rn = 1;
这个查询语句的步骤如下:
ROW_NUMBER()
将每个车辆的记录按照与最接近的 10000 倍数的里程差进行排序,里程差计算为 ABS((mileage / 10000) * 10000 - mileage)
。PARTITION BY vehicle_name
将数据按照车辆名进行分组,并计算每个分组内的排序号码。将上述查询语句应用到你的示例数据,将得到以下结果:
车辆名 日期时间 里程
A 2023-05-11 15:23:23 10001
B 2022-05-12 16:00:31 10100
注意,对于车辆名为 A 的记录,虽然里程最接近 10000 的记录是第一行,但是第二行的里程差也是相同的。根据窗口函数的特性,如果有相同的排序值,将会按照输入数据的顺序选择其中一行。
SELECT * FROM A WHERE ABS(里程-10000)=(SELECT MIN(ABS(里程-10000)) FROM A)
以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:
可以使用窗口函数和子查询来实现。
首先,使用窗口函数计算出每个车辆的每次行驶距离和行驶总里程,然后使用子查询筛选出距离最接近10000的行,最后再使用子查询获取距离最接近10000的行的日期时间和里程。
具体实现如下:
SELECT a.车辆名, subquery.日期时间, subquery.里程
FROM (
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程,
里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶距离
FROM A
) a
JOIN (
SELECT 车辆名, MIN(ABS(行驶总里程 - 10000)) AS 距离差
FROM (
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程
FROM A
) b
GROUP BY 车辆名
) c ON a.车辆名 = c.车辆名 AND ABS(a.行驶总里程 - 10000) = c.距离差
JOIN (
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程
FROM A
) subquery ON a.车辆名 = subquery.车辆名 AND subquery.行驶总里程 = a.行驶总里程
解释一下上面的SQL语句:
首先,使用窗口函数计算出每个车辆的每次行驶距离和行驶总里程,代码如下:
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程,
里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶距离
FROM A
然后,使用子查询筛选出距离最接近10000的行,代码如下:
SELECT 车辆名, MIN(ABS(行驶总里程 - 10000)) AS 距离差
FROM (
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程
FROM A
) b
GROUP BY 车辆名
最后,再使用子查询获取距离最接近10000的行的日期时间和里程,代码如下:
SELECT a.车辆名, subquery.日期时间, subquery.里程
FROM (
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程,
里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶距离
FROM A
) a
JOIN (
SELECT 车辆名, MIN(ABS(行驶总里程 - 10000)) AS 距离差
FROM (
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程
FROM A
) b
GROUP BY 车辆名
) c ON a.车辆名 = c.车辆名 AND ABS(a.行驶总里程 - 10000) = c.距离差
JOIN (
SELECT 车辆名, 日期时间, 里程,
SUM(里程 - LAG(里程, 1, 0) OVER (PARTITION BY 车辆名 ORDER BY 日期时间)) OVER (PARTITION BY 车辆名 ORDER BY 日期时间) AS 行驶总里程
FROM A
) subquery ON a.车辆名 = subquery.车辆名 AND subquery.行驶总里程 = a.行驶总里程