我有一个用户列表。每个用户都有一个分数。我想查询我的数据库以获取11个用户的列表,按分数排序,并以特定记录为中心(我喜欢之前的5条记录,我的查询记录和以下5条记录)
例如,假设下表:
Id Name Score
1 Albert 12
2 Bernard 85
3 Christian 98
4 Danielle 5
5 Emilie 65
6 Fabrice 34
7 Gaston 123
8 Hasting 76
9 Isidor 90
10 Jacques 3
11 Kellam 32
12 Lily 13
13 Mael 4242
如果我使用Emily作为支点运行我的查询,我应该得到以下内容:
5 Danielle --- -5
12 Albert --- -4
13 Lily --- -3
32 Kellam --- -2
34 Fabrice --- -1
65 Emilie --- 0 (pivot)
76 Hasting --- +1
85 Bernard --- +2
90 Isidor --- +3
98 Christian --- +4
123 Gaston --- +5
(请注意Jacques和Mael是如何被退回的,因为他们并未处于要求的范围内)
如何仅使用最少量的查询和/或仅使用简单查询来实现此结果?
我使用的是 Postgres ,但我喜欢的东西也适用于 SQLite
答案 0 :(得分:0)
更新,完全找到5 before
和5 after
emilie
MySQL 5.6架构设置:
CREATE TABLE u
(`Id` int, `Name` varchar(9), `Score` int)
;
INSERT INTO u
(`Id`, `Name`, `Score`)
VALUES
(1, 'Albert', 12),
(2, 'Bernard', 85),
(3, 'Christian', 98),
(4, 'Danielle', 5),
(5, 'Emilie', 65),
(6, 'Fabrice', 34),
(7, 'Gaston', 123),
(8, 'Hasting', 76),
(9, 'Isidor', 90),
(10, 'Jacques', 3),
(11, 'Kellam', 32),
(12, 'Lily', 13),
(13, 'Mael', 4242),
(14, 'a', 65),
(15, 'b', 65),
(16, 'c', 65),
(17, 'd', 65)
;
查询1 :
SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM u
WHERE
Score >= (
SELECT Score
FROM u
WHERE Name = 'Emilie'
)
AND Name != 'Emilie'
ORDER BY Score ASC
LIMIT 5
) a
ORDER BY a.Score DESC
) z
UNION ALL
SELECT *
FROM u
WHERE Name = 'Emilie'
UNION ALL
SELECT *
FROM (
SELECT *
FROM u
WHERE
Score < (
SELECT Score
FROM u
WHERE Name = 'Emilie'
)
ORDER BY Score DESC
LIMIT 5
) w
<强> Results 强>:
| Id | Name | Score |
|----|----------|-------|
| 8 | Hasting | 76 |
| 16 | c | 65 |
| 15 | b | 65 |
| 17 | d | 65 |
| 14 | a | 65 |
| 5 | Emilie | 65 |
| 6 | Fabrice | 34 |
| 11 | Kellam | 32 |
| 12 | Lily | 13 |
| 1 | Albert | 12 |
| 4 | Danielle | 5 |
答案 1 :(得分:0)
Sql Server/Postgresql/Oracle
你可以使用窗口函数:
WITH cte(Score, Name, rn) AS
(
SELECT Score, Name,
ROW_NUMBER() OVER (ORDER BY score) AS rn
FROM tab
)
SELECT Score, Name, rn - (SELECT rn FROM cte WHERE Name = 'Emilie')
FROM cte
WHERE ABS(rn - (SELECT rn FROM cte WHERE Name = 'Emilie')) <=5
ORDER BY Score
的 LiveDemo
强>
输出:
╔═══════╦═══════════╦══════╗
║ Score ║ Name ║ Rank ║
╠═══════╬═══════════╬══════╣
║ 5 ║ Danielle ║ -5 ║
║ 12 ║ Albert ║ -4 ║
║ 13 ║ Lily ║ -3 ║
║ 32 ║ Kellam ║ -2 ║
║ 34 ║ Fabrice ║ -1 ║
║ 65 ║ Emilie ║ 0 ║
║ 76 ║ Hasting ║ 1 ║
║ 85 ║ Bernard ║ 2 ║
║ 90 ║ Isidor ║ 3 ║
║ 98 ║ Christian ║ 4 ║
║ 123 ║ Gaston ║ 5 ║
╚═══════╩═══════════╩══════╝
我认为这个名字是独一无二的。如果不是,您可能需要在子查询中使用TOP 1
和ORDER BY
。更好的方法是使用(SELECT rn FROM cte WHERE id = 5)
,因为Id
是唯一的。
如果得分值相同,您可以将ROW_NUMBER()
更改为DENSE_RANK()
。
答案 2 :(得分:0)
考虑这种通用的SQL解决方案,没有窗口函数,这些函数应该符合大多数RDMS的要求。
您需要手动或动态传递枢轴人员。具有通用编码(VBA,PHP,Python,Java,C#等)或存储过程的参数化查询可以处理:
SELECT [Name], [Score], [rank]
FROM (
SELECT t1.[Name], t1.[Score],
(SELECT Count(*) FROM [pivotTable] t2
WHERE t2.[Score] >= (SELECT t3.[Score] FROM [pivotTable] t3
WHERE t3.[Name]='Emilie')) -
(SELECT Count(*) FROM [pivotTable] t2
WHERE t1.[Score] <= t2.[Score]) As rank
FROM [pivotTable] t1
) AS derivedTbl
WHERE [rank] >= -5 AND [rank] <= 5
ORDER BY [Score]