大家好我的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;
任何人都可以帮助我吗?
非常感谢你。
答案 0 :(得分:3)
使用专有distinct on ()
在Postgres中通常比使用窗口函数更快。
使用abs()建立Gordon的想法:
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
答案 1 :(得分:1)
使用DATEDIFF
获取日期之间的差异,获取ABS
值。然后按ABS(DATEDIFF())
排序并获得最高记录。
答案 2 :(得分:1)
这有点棘手。我认为最好的方法是distinct on
。您没有在问题中描述数据,但这是一个想法:
select distinct on (studentid) s.*
from students s
order by studentid, abs(studentdate - '2015-09-26');
答案 3 :(得分:1)
如果我理解你的要求,这就是答案。 在排名后,它将学生表与学生日期表连接起来,并且只占用最接近您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