Oracle SQL Count 或 Sum 以防万一查询?

Posted

技术标签:

【中文标题】Oracle SQL Count 或 Sum 以防万一查询?【英文标题】:Oracle SQL Count or Sum in case query? 【发布时间】:2018-10-01 21:17:22 【问题描述】:

我在 *** 上研究了五个不同的线程,我觉得我已经接近了,但仍然没有雪茄。我的原始表格有几个部分,每个部分有几行,每行有几个位置。我希望能够查询一个结果,该结果列出了部分、行、位置、有多少位置高于该行(位置编号较低)以及有多少位置低于该行(位置编号更大)。

这是我所拥有的:

SELECT section, 
       row, 
       position AS P, 
       SUM(case when position < P then 1 else 0 end) AS Above, 
       SUM(case when position > P then 1 else 0 end) AS Below 
FROM OriginalTable 
GROUP BY section, row, position 
ORDER BY section, row, position

求和的情况没有将 P 识别为位置,当我将 P 更改为数字时,总和就差了。

【问题讨论】:

您能提供一些示例数据并期待结果吗? P 是在您的 SELECT 子句中定义的别名。您不能在同一个 SELECT 子句中的其他任何地方使用它(例如,在 SUM 或 COUNT 或其他任何内容中的条件中)。这与 COUNT 与 SUM 无关,也与对列别名的有效和无效引用有关。 【参考方案1】:

一种可能的解决方案是相关子查询获取部分和行的较低/较高位置的count()

SELECT ot1.section,
       ot1.row,
       ot1.position,
       (SELECT count(*)
               FROM originaltable ot2
               WHERE ot2.section = ot1.section
                     AND ot2.row = ot2.row
                     AND ot2.position > ot1.position) above,
       (SELECT count(*)
               FROM originaltable ot2
               WHERE ot2.section = ot1.section
                     AND ot2.row = ot2.row
                     AND ot2.position < ot1.position) below
      FROM originaltable ot1
      ORDER BY ot1.section,
               ot1.row,
               ot1.position;

另一个正在使用count()的窗口版本。

SELECT ot1.section,
       ot1.row,
       ot1.position,
       count(*) OVER (PARTITION BY ot1.section,
                                   ot1.row
                      ORDER BY ot1.position
                      RANGE BETWEEN CURRENT ROW
                                    AND UNBOUNDED FOLLOWING) - 1 above
       count(*) OVER (PARTITION BY ot1.section,
                                   ot1.row
                      ORDER BY ot1.position
                      RANGE BETWEEN UNBOUNDED PRECEDING
                                    AND CURRENT ROW) - 1 below
      FROM originaltable ot1
      ORDER BY ot1.section,
               ot1.row,
               ot1.position;

【讨论】:

不使用CURRENT ROW并减去1,你不能使用BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWINGBETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING吗? 在第一个查询中,abovebelow 都有 &lt;。 --- 在第二个查询中,您颠倒了above(位置号较小)和below(位置号较大)的含义。 @Andreas:&lt; 是正确的,更正了,谢谢。对于别名:我的意思是 above 是行“上方”的行数(如果在结果中可视化,则按降序排列)和 below 的模拟。至少这就是我获得OP的方式。不过也可能反过来…… 哇,谢谢@stickybit!两种解决方案都有效,所以这是一个速度问题。上面的选项 1 需要 15.5 秒才能运行,选项 2 以惊人的 0.00 秒运行。【参考方案2】:

我只会使用row_number():

SELECT section, row, position AS P, 
       ROW_NUMBER() OVER (PARTITION BY section, row ORDER BY position ASC) - 1 as Above,
       ROW_NUMBER() OVER (PARTITION BY section, row ORDER BY position DESC) - 1 as Below
FROM OriginalTable
ORDER BY section, row, position;

如果你有重复,那么问题就有点棘手了(尽管GROUP BY 会解决这个问题)。您可能需要DENSE_RANK() 而不是ROW_NUMBER()

【讨论】:

谢谢戈登。您的解决方案运行良好,速度很快(0.015 秒),但不如上面的@stickybit 解决方案#2 快。出色的工作和干净整洁的代码。 @ToddK 。 . .它们在性能上应该差不多。以毫秒为单位测量经过的时间需要非常小心 - 考虑到服务器负载、热缓存等因素。

以上是关于Oracle SQL Count 或 Sum 以防万一查询?的主要内容,如果未能解决你的问题,请参考以下文章

oracle查询选择语句——count、sum、order by、group by

sql语句写法(sum和count)

具有 SUM、COUNT 或聚合结果的动态列的 SQL Pivot

查询分组中的 Oracle SQL 条件聚合函数

Oracle种常用性能监控SQL语句

oracle 中 sum 如何使用,