到目前为止,我列出了本赛季击败大满贯的球员名单。
___________________________________________________
| Player Name | dateOfGrandSlam | distance | home |
---------------------------------------------------
| Griffin | 9-14-2013 | 413 | true |
| Griffin | 10-1-2013 | 371 | false|
| Simpson | 5-15-2013 | 413 | true |
| Reid | 7-1-2013 | 362 | true |
| Reid | 7-4-2013 | 363 | true |
| Reid | 9-28-2013 | 388 | true |
| Peavis | 8-14-2013 | 466 | false|
我想得到一份最近的grandslam在家的球员名单。如果他们最近的grandslam不在家,我不希望他们出现在我的名单上。 这意味着,我需要通过播放器选择播放器和组,并从该组中选择最大日期。在该列表中,我还必须包含家/外信息,以便我可以选择那些不在家的信息。
但是我遇到了问题。因为要选择属性home
,我还需要在home
子句中包含GROUP BY
。
例如:
SELECT playerName, MAX(date), distance, home
FROM grandslams
GROUP BY playerName, distance, home
问题是这会返回一张表格,其中包含最近的房屋和最近的房屋。
| Player Name | dateOfGrandSlam | distance | home |
---------------------------------------------------
| Griffin | 9-14-2013 | 413 | true |
| Griffin | 10-1-2013 | 371 | false|
| Simpson | 5-15-2013 | 413 | true |
| Reid | 9-28-2013 | 388 | true |
这不是我想要的 - 如果最近没有远处的grandslams,我只想要最近的家庭grandslams。
我想要这个结果:
___________________________________________________
| Player Name | dateOfGrandSlam | distance | home |
---------------------------------------------------
| Simpson | 5-15-2013 | 413 | true |
| Reid | 9-28-2013 | 388 | true |
基本上我需要一种方法来执行查询,这个查询只会让我获得每位玩家最近的grandslam,对home
属性进行处理(不必分组,所以我不知道得到他最近的房子和他最近的房子)然后可以在外部查询中轻松过滤。
换句话说,我需要从
获得结果SELECT playerName, MAX(date), distance
FROM grandSlams
GROUP BY playerName, distance
并将home
属性附加到其中。
答案 0 :(得分:3)
您可以使用row_number()
功能查找每位玩家的最新大满贯,并按日期降序排列。要选择最新的,请选择值为1的那个。然后在家中的大满贯中添加条件:
select gs.*
from (select gs.*,
row_number() over (partition by PlayerName
order by dateOfGrandSlam desc) as seqnum
from GrandSlams gs
) gs
where seqnum = 1 and home = true;
答案 1 :(得分:0)
您可以先找到所有最后的本垒打,然后将它们连接到原始表格。
SELECT g.* from (SELECT playerName, MAX(date) date
FROM grandslams
GROUP BY playerName) a
NATURAL JOIN grandslams g
WHERE g.home = true;
如果您不是自然加入的粉丝(为了ansi的缘故),您可以随时使用
JOIN grandslams g on g.playerName = a.playerName and g.date = a.date
而不是自然连接。 这将使查询ansi。
答案 2 :(得分:0)
解决问题。
1)建立一个查询,让你找到最后一击在家的球员。即,他们最近的家庭大满贯是他们最近的大满贯。
SELECT
playerName,
MAX(dateOfGrandSlam) mostRecentGrandSlam
FROM grandSlams
GROUP BY playerName
HAVING MAX(CASE home WHEN 'true' THEN dateOfGrandSlam END) = MAX(dateOfGrandSlam)
2)使用该查询将原始表格过滤为您想要的行:
SELECT a.playerName, a.dateOfGrandSlam, a.distance, a.home
FROM grandSlams a
INNER JOIN (
SELECT
playerName,
MAX(dateOfGrandSlam) mostRecentGrandSlam
FROM grandSlams
GROUP BY playerName
HAVING MAX(CASE home WHEN 'true' THEN dateOfGrandSlam END) = MAX(dateOfGrandSlam)
) b ON (a.playerName = b.playerName AND a.dateOfGrandSlam = b.mostRecentGrandSlam)
答案 3 :(得分:0)
基本查询最简单 DISTINCT ON
,这是SQL标准的 Postgres特定扩展名{ {1}}:
DISTINCT
将效果与EXPLAIN ANALYZE
进行比较。本相关答案的详细说明:
Select first row in each GROUP BY group?
使用子查询来消除最近的grandslam不在家的案例:
SELECT DISTINCT ON (playername)
playername, dateofgrandslam, distance, home
FROM grandslams
GROUP BY playername, dateofgrandslamDESC;
性能王冠的另一个热门竞争者(取决于你需要的确切),以及纯粹的标准SQL :NOT EXISTS
反半连接。也比听起来简单:
SELECT * FROM (
SELECT DISTINCT ON (playername)
playername, dateofgrandslam, distance, home
FROM grandslams
GROUP BY playername, dateofgrandslam DESC
) sub
WHERE home;
除此之外:使用SELECT playername, dateofgrandslam, distance, home
FROM grandslams g
WHERE home
AND NOT EXISTS (
SELECT 1
FROM grandslams g1
WHERE g1.playername = g.playername
AND g1.dateofgrandslam > g.dateofgrandslam
);
的小写字母,因为在Postgres中无论如何都会将不带引号的标识符强制转换为小写。