限制 SQL 查询,以便特定列中的任何特定值在结果中只能出现 3 次,相对于给定的顺序
Restricting a SQL query so that any particular value in a certain column can only appear 3 times in the results, with respect to a given ordering
假设我在 SQL 数据库中有一个 table,其列如下所示。 table记录了我公司员工每个月的各种绩效指标。
我可以很容易地查询 table 这样我就可以看到我的员工获得的最好的月度销售数据,以及负责的员工和获得该数据的月份:
SELECT * FROM EmployeePerformance ORDER BY Sales DESC;
NAME MONTH SALES COMMENDATIONS ABSENCES
Karen Jul 16 36,319.13 2 0
David Feb 16 35,398.03 2 1
Martin Nov 16 33,774.38 1 1
Sandra Nov 15 33,012.55 4 0
Sandra Mar 16 31,404.45 1 0
Karen Sep 16 30,645.78 2 2
David Feb 16 29,584.81 1 1
Karen Jun 16 29,030.00 3 0
Stuart Mar 16 28,877.34 0 1
Karen Nov 15 28,214.42 1 2
Martin May 16 28,091.99 3 0
这个查询很简单,但不是我想要的。如果我想在结果集中只看到每个员工每月取得的前 3 个数字,我需要如何更改它?
换句话说,我想写一个与上面相同的查询,但是如果任何员工在结果集中出现超过 3 次,那么应该只包括他们的前 3 个结果, 他们的任何进一步结果都应该被忽略。在我的示例查询中,Karen 从 11 月 15 日开始的数字将不再包括在内,因为根据 "ORDER BY Sales DESC".
的排序,她已经有其他三个数字高于该数字
我正在使用的特定 SQL 数据库是 SQLite,或者,如果 SQLite 无法满足我的需要,那么 MySQL.
在MySQL中你可以使用windows函数:
SELECT *
FROM EmployeePerformance
WHERE row_number() OVER (ORDER BY Sales DESC)<=3
ORDER BY Sales DESC
在 SQLite 中 window 函数不可用,但您仍然可以计算前面的行数:
SELECT *
FROM EmployeePerformance e
WHERE
(SELECT COUNT(*)
FROM EmployeePerformance ee
WHERE ee.Name=e.Name and ee.Sales>e.Sales)<3
ORDER BY e.Sales DESC
我自己找到了答案。它的工作原理似乎是将每条记录与来自同一个人的所有等于或大于的记录配对,然后仅选择不超过 3 个大于或等于配对的(左)记录。
SELECT P.Name, P.Month, P.Sales, P.Commendations, P.Absences
FROM Performance P
LEFT JOIN Performance P2 ON (P.Name = P2.Name AND P.Sales <= P2.Sales)
GROUP BY P.Name, P.Month, P.Sales, P.Commendations, P.Absences
HAVING COUNT(*) <= 3
ORDER BY P.Sales DESC;
我将感谢 a_horse_with_no_name 添加了标签 "greatest-n-per-group",否则我将不知道要搜索什么,并且通过使用此标签查看其他问题我设法解决了找到我想要的。
我发现这个问题和我的很相似...Using LIMIT within GROUP BY to get N results per group?
然后我遵循了这个 link 有人在评论中包含的... https://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
...我想要的答案在那篇文章的第一条评论中。它非常完美,因为它只使用一个 LEFT JOIN,所以它可以在 SQLite.
中工作
这是我的SQLFiddle:http://sqlfiddle.com/#!7/580f0/5/0
假设我在 SQL 数据库中有一个 table,其列如下所示。 table记录了我公司员工每个月的各种绩效指标。
我可以很容易地查询 table 这样我就可以看到我的员工获得的最好的月度销售数据,以及负责的员工和获得该数据的月份:
SELECT * FROM EmployeePerformance ORDER BY Sales DESC;
NAME MONTH SALES COMMENDATIONS ABSENCES
Karen Jul 16 36,319.13 2 0
David Feb 16 35,398.03 2 1
Martin Nov 16 33,774.38 1 1
Sandra Nov 15 33,012.55 4 0
Sandra Mar 16 31,404.45 1 0
Karen Sep 16 30,645.78 2 2
David Feb 16 29,584.81 1 1
Karen Jun 16 29,030.00 3 0
Stuart Mar 16 28,877.34 0 1
Karen Nov 15 28,214.42 1 2
Martin May 16 28,091.99 3 0
这个查询很简单,但不是我想要的。如果我想在结果集中只看到每个员工每月取得的前 3 个数字,我需要如何更改它?
换句话说,我想写一个与上面相同的查询,但是如果任何员工在结果集中出现超过 3 次,那么应该只包括他们的前 3 个结果, 他们的任何进一步结果都应该被忽略。在我的示例查询中,Karen 从 11 月 15 日开始的数字将不再包括在内,因为根据 "ORDER BY Sales DESC".
的排序,她已经有其他三个数字高于该数字我正在使用的特定 SQL 数据库是 SQLite,或者,如果 SQLite 无法满足我的需要,那么 MySQL.
在MySQL中你可以使用windows函数:
SELECT *
FROM EmployeePerformance
WHERE row_number() OVER (ORDER BY Sales DESC)<=3
ORDER BY Sales DESC
在 SQLite 中 window 函数不可用,但您仍然可以计算前面的行数:
SELECT *
FROM EmployeePerformance e
WHERE
(SELECT COUNT(*)
FROM EmployeePerformance ee
WHERE ee.Name=e.Name and ee.Sales>e.Sales)<3
ORDER BY e.Sales DESC
我自己找到了答案。它的工作原理似乎是将每条记录与来自同一个人的所有等于或大于的记录配对,然后仅选择不超过 3 个大于或等于配对的(左)记录。
SELECT P.Name, P.Month, P.Sales, P.Commendations, P.Absences
FROM Performance P
LEFT JOIN Performance P2 ON (P.Name = P2.Name AND P.Sales <= P2.Sales)
GROUP BY P.Name, P.Month, P.Sales, P.Commendations, P.Absences
HAVING COUNT(*) <= 3
ORDER BY P.Sales DESC;
我将感谢 a_horse_with_no_name 添加了标签 "greatest-n-per-group",否则我将不知道要搜索什么,并且通过使用此标签查看其他问题我设法解决了找到我想要的。
我发现这个问题和我的很相似...Using LIMIT within GROUP BY to get N results per group?
然后我遵循了这个 link 有人在评论中包含的... https://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
...我想要的答案在那篇文章的第一条评论中。它非常完美,因为它只使用一个 LEFT JOIN,所以它可以在 SQLite.
中工作这是我的SQLFiddle:http://sqlfiddle.com/#!7/580f0/5/0