SQL 从至少有一个来自异性的表中获得前 3 名

Posted

技术标签:

【中文标题】SQL 从至少有一个来自异性的表中获得前 3 名【英文标题】:SQL to get top 3 from a table with at least one from opposite gender 【发布时间】:2018-03-29 23:15:34 【问题描述】:

我有一个这样的数据库表

用户

id  Capacity Gender
----------------------
1     10     M
---------------------
2     9      M
---------------------
3     4      F
---------------------
4     8      M
---------------------
5     7      F
---------------------

我想使用 SQL 检索按容量排序的前 3 条记录,其中至少有一条来自异性,如下所示

id  Capacity Gender
----------------------
1     10     M
---------------------
2     9      M
---------------------
5     7      F
---------------------

由于我没有使用 oracle,因此我无法使用“分区方式”,我想要一个适用于 H2 数据库或与数据库无关的数据库(如果可能)。

提前致谢

山姆

【问题讨论】:

我删除了标签 sql,因为您的表格是 html 格式。真的是sql还是html? 对不起,我现在编辑了,我正在寻找sql解决方案。 在我看来,最简单的做法是选择性别 = M 的前 2 个和性别 = F 的前 2 个,然后选择其中的前 3 个。 谢谢我放回标签sql 【参考方案1】:

这是相当长的,因为要求也很严格。 它正在利用自我加入和分组。 获取每个性别的前 2 名,以确保代表两个性别组。然后获得前三名。

SELECT id, capacity, gender
from (
SELECT t.id, t.gender, t.capacity,
       COUNT(*) AS rn
FROM t
   JOIN t AS t2
    ON  t2.gender = t.gender
   AND ( t2.capacity > t.capacity
          OR  t2.capacity = t.capacity
        AND t2.id <= t.id )
GROUP BY t.id, t.gender, t.capacity
HAVING COUNT(*) <= 2
ORDER BY t.capacity desc, rn ) tab
ORDER BY capacity desc 
LIMIT 3;

Result:
id  capacity    gender
1      10   M
2       9           M
5       7            F

【讨论】:

这适用于 mysql、oracle 和 sqllite。对于 sqlserver,您可以放置​​ TOP 3 并删除 Limit 3。 顺便说一句,我没有 H2 的经验。 嗨,非常感谢,它适用于 H2 上的这个数据集。让我根据我的情况对其进行调整并进行更多测试。 如果可行,请点赞并接受我的回答。谢谢。【参考方案2】:

这可能有点老套,但我相信它适用于您的问题。请尝试:

CREATE TABLE temp as
Select top 2 id, Gender, max(capacity) as maxcap
from table
where Gender ='F'
group by id, Gender 

CREATE TABLE temp2 as
Select top 2 id, Gender, max(capacity) as maxcap
from table
where Gender ='M'
group by id, Gender 

select top 3 id, gender, maxcap
from
(
   Select id, Gender, maxcap
   from temp
   union
   Select Gender, maxcap
   from temp2
) t
order by t.maxcap desc

【讨论】:

我认为您也需要订购 temp 和 temp2。那里的 max() 和组没有添加任何东西,所以你总是得到前两条记录。如果您可以将其作为 CTE 执行此操作会更整洁,因为 H2 从外观上看不支持每个连接的临时表。 嗨,Eray,感谢您的想法。我想在不使用临时表的情况下在单个 sql 语句中执行此操作。山姆【参考方案3】:

这是一个 CTE 答案,基于大卫康拉德的 cmets 方法:

with f(id, gender, capacity) as (select top 2 id, gender, capacity from capacity
                                        where gender = 'F' order by capacity desc),
     m(id, gender, capacity) as (select top 2 id, gender, capacity from capacity
                                        where gender = 'M' order by capacity desc),
     combined(id, gender, capacity) as (select * from f union select * from m)
select top 3 * from combined order by capacity desc;

(假设该表也称为“容量”)。如果没有 RANK() 函数,我看不出如何做得更好,而且我对 subquery count rank function suggested here 在大桌子上的表现感到紧张,如果你也走这条路,你必须小心平局.在 H2 和 SQL Server 上测试。

【讨论】:

以上是关于SQL 从至少有一个来自异性的表中获得前 3 名的主要内容,如果未能解决你的问题,请参考以下文章

sql 从具有限制的表中删除(排除前X行)

从sql中的表中检索前n个字母[重复]

如何从 T-SQL 中的表中选择前 N 行?

在pl/sql中怎么查询所有存在的表,以及怎么样获得未知表中的某一字段

Java 中获得Access 数据库中的表名和表中的列名 及每个列的数据类型

为什么我的SQL Server审核触发器搞乱了来自Access的ODBC调用/刷新?