我正在使用PostgreSQL数据库。
这个想法:
这里有一种数据库:
id | user_id | game_id | mini_game_id | result | created_at
-----------------------------------------------------------
70 | 44 | 105 | 22 | 19 | 28/11/2016
69 | 44 | 105 | 20 | 18 | 28/11/2016
68 | 44 | 104 | 22 | 17 | 27/11/2016
67 | 44 | 104 | 21 | 16 | 27/11/2016
66 | 44 | 103 | 22 | 15 | 26/11/2016
65 | 44 | 103 | 21 | 14 | 26/11/2016
64 | 44 | 103 | 20 | 13 | 26/11/2016
我希望在最新游戏结束时显示,除了每个mini_game的结果之外,还显示之前相同的mini_game的结果。
示例:对于user 44
,在game 105
的末尾,我想获取此数据:
id | game_id | mini_game_id | second-to-last-result | date
-----------------------------------------------------------------
68 | 104 | 22 | 17 | 27/11/2016
64 | 103 | 20 | 13 | 26/11/2016
SELECT mini_game_id,
array_agg(result) as results,
array_agg(created_at) as dates
FROM result
WHERE user_id = 44
AND game_id != 105 --Exclude latest game
GROUP BY mini_game_id
ORDER BY mini_game_id
结果:
mini_game_id | results | dates
--------------------------------------------------
22 | {17, 15} | {27/11/2016, 26/11/2016}
21 | {16, 14} | {27/11/2016, 26/11/2016}
20 | {13} | {26/11/2016}
在这里,问题是我得到每个游戏的每个mini_game的每个结果给用户,这对我来说似乎有点过分,因为我可以有数千个结果......
SELECT id,
game_id,
mini_game_id,
result,
created_at
FROM result
WHERE user_id = 44
AND game_id != 105 --Exclude latest game
AND mini_game IN (22, 20) --The two mini-games the user have played in game 105
ORDER BY created_at DESC
LIMIT 1
id | game_id | mini_game_id | result | created_at
--------------------------------------------------
68 | 104 | 22 | 17 | 27/11/2016
显然,我只得到1个结果。但我的想法是limit 1
WHERE IN
你能帮我理解我是怎么做到的吗? 感谢
答案 0 :(得分:1)
WITH cte AS (
SELECT *
,DENSE_RANK() OVER (PARTITION by user_id ORDER BY created_at DESC) as LatestGame
,LAG(result) OVER (PARTITION BY user_id, mini_game_id ORDER BY created_at) as SecondToLastResult
FROM
Table
)
SELECT
id
,game_id
,mini_game_id
,result
,SecondToLastResult
,created_at as Date
FROM
cte
WHERE
LatestGame = 1
;
使用DENSE_RANK()
定义最新游戏,使用LAG()
获取上一个结果,然后从公用表格[cte]
LatestGame
= 1的位置
这是postgresql关于窗口函数的链接:https://www.postgresql.org/docs/8.4/static/functions-window.html
要过滤到只有1个用户,您可以执行以下操作,因为您不再需要按user_id对窗口功能进行分区:
WITH cte AS (
SELECT *
,DENSE_RANK() OVER (ORDER BY created_at DESC) as LatestGame
,LAG(result) OVER (PARTITION BY mini_game_id ORDER BY created_at) as SecondToLastResult
FROM
Table
WHERE
user_id = 44
)
这里只是为了好玩,你可以使用窗口函数来完成它:
SELECT
t.id
,t.user_id
,t.game_id
,t.mini_game_id
,t.result
,t.created_at
,(SELECT result
FROM
Table t2
WHERE
t.user_id = t2.user_id
AND t.mini_game_id = t2.mini_game_id
AND t.created_at > t2.created_at
ORDER BY
t2.created_at DESC
LIMIT 1) as SecondToLastResult
FROM
Table t
LEFT JOIN Table t1
ON t.user_id = t1.user_id
AND t.created_at < t1.created_at
WHERE
t1.id IS NULL
AND t.user_id = 44
我认为窗口函数会更适合你。