SQL - 根据特定列上的出现从 select 中删除元组
SQL - Remove tuples from a select based on occurences on a specific column
考虑代表种族历史的简单 table:
laphistory(race_id integer,lap_number integer,pos_number integer,
driver_label text,id integer NOT NULL,CONSTRAINT id PRIMARY KEY (id) ...)
现在,考虑以下示例:
race_id;lap_number;pos_number;driver_label;id
1 ;1 ;1 ;"Matheus" ;1
1 ;1 ;2 ;"Nicolas" ;2
1 ;1 ;3 ;"Diego" ;3
1 ;2 ;1 ;"Nicolas" ;4
1 ;2 ;2 ;"Diego" ;5
1 ;2 ;3 ;"Matheus" ;6
1 ;3 ;1 ;"Nicolas" ;7
1 ;3 ;2 ;"Diego" ;8
1 ;4 ;1 ;"Diego" ;9
根据上面的例子,第一场比赛的结果(对每个车手最后一圈的位置进行排序)应该是(这里可以忽略"pos_number"):
race_id;lap_number;pos_number;driver_label;id
1 ;4 ;1 ;"Diego" ;9
1 ;3 ;1 ;"Nicolas" ;7
1 ;2 ;3 ;"Matheus" ;6
使用简单查询查询 BD:
select * from laphistory order by lap_number DESC, pos_number ASC
会带来如下结果:
race_id;lap_number;pos_number;driver_label;id
1 ;4 ;1 ;"Diego" ;9 <<<
1 ;3 ;1 ;"Nicolas" ;7 <<<
1 ;3 ;2 ;"Diego" ;8
1 ;2 ;1 ;"Nicolas" ;4
1 ;2 ;2 ;"Diego" ;5
1 ;2 ;3 ;"Matheus" ;6 <<<
1 ;1 ;1 ;"Matheus" ;1
1 ;1 ;2 ;"Nicolas" ;2
1 ;1 ;3 ;"Diego" ;3
如果我们考虑每个driver.However的第一次出现是正确的,我不知道如何select。有什么想法吗?
可以应用 PostgreSQL 的 window function
以获得所需的输出:
SELECT *
FROM (
SELECT *
,row_number() OVER (
PARTITION BY driver_label ORDER BY lap_number DESC
) AS rank
FROM race
) t
WHERE rank = 1
或者
SELECT DISTINCT ON (driver_label) *
FROM race
ORDER BY driver_label ASC
,lap_number DESC
简单的 GROUP BY 应该可以满足您的需要:
select race_id, lap_number, min(id) from foo
group by race_id, lap_number
order by race_id asc, lap_number desc
感谢 Vivek.S 的精彩回答,我找到了解决方案。刚刚做了一些改编:
SELECT *
FROM (
SELECT *
,row_number() OVER (
PARTITION BY driver_label ORDER BY lap_number DESC
) AS rank
FROM laphistory where lap_number<= $X$
) t
WHERE rank = 1 order by lap_number DESC, pos_number ASC
现在我可以让车手订购一圈 $x$。
谢谢!
考虑代表种族历史的简单 table:
laphistory(race_id integer,lap_number integer,pos_number integer,
driver_label text,id integer NOT NULL,CONSTRAINT id PRIMARY KEY (id) ...)
现在,考虑以下示例:
race_id;lap_number;pos_number;driver_label;id
1 ;1 ;1 ;"Matheus" ;1
1 ;1 ;2 ;"Nicolas" ;2
1 ;1 ;3 ;"Diego" ;3
1 ;2 ;1 ;"Nicolas" ;4
1 ;2 ;2 ;"Diego" ;5
1 ;2 ;3 ;"Matheus" ;6
1 ;3 ;1 ;"Nicolas" ;7
1 ;3 ;2 ;"Diego" ;8
1 ;4 ;1 ;"Diego" ;9
根据上面的例子,第一场比赛的结果(对每个车手最后一圈的位置进行排序)应该是(这里可以忽略"pos_number"):
race_id;lap_number;pos_number;driver_label;id
1 ;4 ;1 ;"Diego" ;9
1 ;3 ;1 ;"Nicolas" ;7
1 ;2 ;3 ;"Matheus" ;6
使用简单查询查询 BD:
select * from laphistory order by lap_number DESC, pos_number ASC
会带来如下结果:
race_id;lap_number;pos_number;driver_label;id
1 ;4 ;1 ;"Diego" ;9 <<<
1 ;3 ;1 ;"Nicolas" ;7 <<<
1 ;3 ;2 ;"Diego" ;8
1 ;2 ;1 ;"Nicolas" ;4
1 ;2 ;2 ;"Diego" ;5
1 ;2 ;3 ;"Matheus" ;6 <<<
1 ;1 ;1 ;"Matheus" ;1
1 ;1 ;2 ;"Nicolas" ;2
1 ;1 ;3 ;"Diego" ;3
如果我们考虑每个driver.However的第一次出现是正确的,我不知道如何select。有什么想法吗?
可以应用 PostgreSQL 的 window function
以获得所需的输出:
SELECT *
FROM (
SELECT *
,row_number() OVER (
PARTITION BY driver_label ORDER BY lap_number DESC
) AS rank
FROM race
) t
WHERE rank = 1
或者
SELECT DISTINCT ON (driver_label) *
FROM race
ORDER BY driver_label ASC
,lap_number DESC
简单的 GROUP BY 应该可以满足您的需要:
select race_id, lap_number, min(id) from foo
group by race_id, lap_number
order by race_id asc, lap_number desc
感谢 Vivek.S 的精彩回答,我找到了解决方案。刚刚做了一些改编:
SELECT *
FROM (
SELECT *
,row_number() OVER (
PARTITION BY driver_label ORDER BY lap_number DESC
) AS rank
FROM laphistory where lap_number<= $X$
) t
WHERE rank = 1 order by lap_number DESC, pos_number ASC
现在我可以让车手订购一圈 $x$。 谢谢!