[英]Get closest date to given date for a group of records
嗨,大家好,我在使用SQL查询时遇到问题,这是我的情况:
我有一个学生表和一个用于存储学生入学或离校时的日期的表,因此我想为每个学生获取到给定日期的最接近日期,我找不到解决方法。
Students Data:
|idstudent|name |
------------------
| 1 | John |
| 2 | Bob |
------------------
Dates Data:
|id|idstudent| date |type|
------------------------------
|1 | 1 |20-01-2015| 1 |
|2 | 2 |20-01-2015| 1 |
|3 | 2 |15-08-2015| 2 |
|4 | 1 |31-08-2015| 2 |
------------------------------
Desired Date = 01-08-2015
|idstudent| name | date |type|
-------------------------------------
| 1 | John | 31-08-2015 | 2 |
| 2 | Bob | 15-08-2015 | 2 |
学生表:
CREATE TABLE students
(
idstudent serial NOT NULL,
name character varying(200),
CONSTRAINT idstudent PRIMARY KEY (idstudent)
)
WITH (
OIDS=FALSE
);
ALTER TABLE students
OWNER TO postgres;
日期表:
CREATE TABLE students_dates
(
idstudent_date serial NOT NULL,
idstudent bigint,
date_ date,
type smallint,
CONSTRAINT idstudent_date PRIMARY KEY (idstudent_date)
)
WITH (
OIDS=FALSE
);
ALTER TABLE students_dates
OWNER TO postgres;
谁能帮我?
非常感谢。
在Postgres中,使用专有的distinct on ()
通常比使用窗口函数要快。
用abs()建立戈登的想法:
select distinct on (s.idstudent) s.*, sd.date_, sd.type
from students s
join students_dates sd on s.idstudent = sd.idstudent
order by s.idstudent, abs(sd.date_ - date '2015-09-26');
这也可以使用Window函数来解决:
select idstudent, name, date_, type
from (
select s.idstudent, s.name, sd.date_, sd.type,
row_number() over (partition by s.idstudent order by sd.date_ - date '2015-09-26' desc) as rn
from students s
join students_dates sd on s.idstudent = sd.idstudent
) t
where rn = 1;
SQLFiddle: http ://sqlfiddle.com/#!15/25fef/4
使用DATEDIFF
获取日期之间的差,获取ABS
值。 然后按ABS(DATEDIFF())
排序并获得最高记录。
这有点棘手。 我认为最好的方法distinct on
。 您没有描述问题中的数据,但这是一个主意:
select distinct on (studentid) s.*
from students s
order by studentid, abs(studentdate - '2015-09-26');
如果我理解您的要求,这就是答案。 它将RANKED之后的学生表与学生日期表结合在一起,并且仅采用最接近您GIVEN_DATE的日期。
SELECT s.* FROM students s
INNER JOIN
(SELECT date,type FROM (
SELECT sd2.*,RANK() OVER(PARTITION BY sd2.idstudent ORDER BY abs(sd2.date - GIVEN_DATE) ASC) as sdrank
FROM students_dates sd2
) where sdrank = 1) sd on sd.idstudent = s.idstudent
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.