对多个参数执行“SELECT TOP 5”的最简单方法是啥?

Posted

技术标签:

【中文标题】对多个参数执行“SELECT TOP 5”的最简单方法是啥?【英文标题】:What is the simplest way to do "SELECT TOP 5" for multiple parameters?对多个参数执行“SELECT TOP 5”的最简单方法是什么? 【发布时间】:2019-01-15 13:16:59 【问题描述】:

我正在尝试在 LibreOffice Base / HSQLDB 中构建一个新数据库,据称它支持标准 SQL,但可能不如 SQL-server 或 Oracle 广泛。

我有一个分数表,其中参与者是俱乐部列表中的一个成员。我需要在团队动态的情况下生成“团队分数”,即它们由每个俱乐部的前 5 名得分组成。

到目前为止,我能够达到的最接近的是:

SELECT "Score", "ShootRecords"."ClubID" FROM  "ShootRecords" WHERE "ShootRecords"."ClubID" = 0

UNION 

SELECT "Score", "ShootRecords"."ClubID" FROM  "ShootRecords" WHERE "ShootRecords"."ClubID" = 1

ORDER BY "Score" DESC

如果我在每个子查询的开头添加 TOP 5 限定符,它会报告为无效 SQL。 如果我将ORDER BY 子句移动到子查询中,它再次报告为无效SQL,但每个子查询都需要按这种方式排序,并且限制为TOP 5 否则结果错误。

我也看过这样的子查询:

SELECT "ClubID"

FROM   "Clubs"

WHERE  "Clubs"."ClubID" IN

   (SELECT "ClubID"

    FROM "Clubs", "ShootRecords"

    WHERE "Clubs"."ClubID" = "ShootRecords"."ClubID"
    )

但排序和子设置再次以错误的顺序完成,或者无效。

我希望看到的是这样的:

Score     ClubID
------------------
300        0
299        0
280        0
200        0
190        0
310        1
290        1
277        1

等等

【问题讨论】:

应该很简单。请添加一些示例数据和预期结果。 您是否尝试在每个联合查询中添加ORDER BY "Score" DESC LIMIT 5? (ref)。另外,我认为在这种情况下UNION ALL 会更好。 另外,TOP 5 不是标准 SQL。附加LIMIT 5(这也不是标准的,但得到很好的支持)。 LIMIT 5 也不是标准 SQL; FETCH FIRST 5 ROWS 是。但是,是的,HSQLDB 想要LIMIT 5 出现平局怎么办?我猜是从绑定的成员中任意选择一个成员? 【参考方案1】:

为了使您自己的查询正常工作,您需要为每个部分查询添加一个 ORDER BY(和 LIMIT)子句。为此,请使用括号:

(
  SELECT Score, ClubID 
  FROM ShootRecords 
  WHERE ShootRecords.ClubID = 0
  ORDER BY Score DESC
  LIMIT 5
)
UNION ALL
(
  SELECT Score, ClubID 
  FROM ShootRecords 
  WHERE ShootRecords.ClubID = 1
  ORDER BY Score DESC
  LIMIT 5
)
ORDER BY ClubID, Score DESC;

顺便说一句,我是UNION ALLUNION [DISTINCT] 是一种特殊的联合形式,可以去除重复项。

【讨论】:

就是这样 - 我第一次看到 UNION 的示例,子查询周围有括号。其余的都很好,只是没有被解析为两个不同的查询。【参考方案2】:

每组 TOP n 查询通常使用分析函数解决,但 HSQLDB 不支持。

无论如何,进入前五名意味着只有不到五个更好。

select *
from  shootrecords sr
where 5 >
(
  select count(*)
  from shootrecords better
  where better.clubid = sr
  and 
  (  better.score > sr.score
      or 
    (better.score = sr.score and better.memberid < sr.memberid) -- for the case of ties
  )
)
order by clubid, score, memberid;

如果出现平局(多个成员得分相同)我必须任意选择成员。我先选择那些 ID 最低的。

【讨论】:

以上是关于对多个参数执行“SELECT TOP 5”的最简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 对 C 代码进行单元测试的最简单方法

从每个参数中删除尾部斜杠的最简单方法是啥?

使用 std::ostream 打印可变参数包的最简单方法是啥?

linux中设计一个shell脚本程序可以接受命令行输入的参数执行相应的菜单命令

在多个 iOS 和 Android 设备之间保持数据库同步的最简单方法是啥?

在 2D 矢量中的预定位置更改多个值的最简单方法是啥?