繁体   English   中英

获取一组记录与给定日期的最接近日期

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM