Oracle-如何以最小/最大速率显示[公寓]总数(嵌套的汇总函数问题)

时间:2019-04-26 22:13:21

标签: oracle11g max aggregate-functions min

我想发现最简单/性能最低的方法,以在一行数据中显示组中有多少条记录与要分组的数据中的最小/最大速率相匹配。在我的示例中,建筑物被分组。

在我提供的伪代码中,我还希望与现有列一起提供另外两列,以显示每栋建筑物中有多少套公寓的房价与每栋建筑物的最低/最高房价相匹配。凭直觉,我认为我所要做的就是计算每次入住率均与小组的最低/最高比率相匹配的情况。这里的问题是我现在正在嵌套聚合函数,但是没有解决。也许我缺少一些简单的东西。

在此版本的查询中(伪代码比我的实际代码简单得多),我可以只包装查询,然后使用最小值/最大值与外部查询中的街道价格进行比较,但我正在寻找如果我能够将MIN(rate)嵌套在CASE和SUM()中,那么一种简单的方法可能与伪代码一样简单。除了使查询复杂之外,我不确定是否有简单的方法。

不起作用的特定行是LINE 20: SUM(CASE WHEN rate = MIN(rate) THEN 1 ELSE 0 END) AS tot_min_rates。我已将其注释掉。

WITH rates AS
(
  SELECT 1001 AS apt_Key, 5  AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1002 AS apt_Key, 4  AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1003 AS apt_Key, 17 AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1004 AS apt_Key, 10 AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1005 AS apt_Key, 4  AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1006 AS apt_Key, 7  AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1007 AS apt_Key, 5  AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1008 AS apt_Key, 13 AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1009 AS apt_Key, 10 AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1010 AS apt_Key, 13 AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1011 AS apt_Key, 8  AS rate, 130 AS building FROM dual
) /* END rates CTE */

SELECT COUNT(apt_key) AS tot_apts, building
  , ROUND(AVG(rate),1) AS avg_rate
  , MIN(rate) AS min_rate
  , MAX(rate) AS max_rate  
  -- SUM(CASE WHEN rate = MIN(rate) THEN 1 ELSE 0 END) AS tot_min_rates  
FROM rates
GROUP BY building
;

enter image description here

1 个答案:

答案 0 :(得分:0)

据我所知,似乎没有一种方法可以在不使用子选择或虚拟表或CTE的情况下,使它在同一简单查询中运行。试图做rate = MAX(rate)只是SQL无法识别。据我所知,当您尝试执行此操作时,没有数据库引擎会发挥很好的作用。笨蛋

我在下面找到的链接用于MS ACCESS,但这是同样的问题。

Use SQL to display count of min and count of max within group

尽管上述链接中的解决方案有效,但我更喜欢易于阅读和重用通用表表达式(CTE)来组织查询的问题,下面是我正在使用的解决方案。

WITH rates AS
(
  SELECT 1001 AS apt_Key, 5  AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1002 AS apt_Key, 4  AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1003 AS apt_Key, 17 AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1004 AS apt_Key, 10 AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1005 AS apt_Key, 4  AS rate, 120 AS building FROM dual UNION ALL
  SELECT 1006 AS apt_Key, 7  AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1007 AS apt_Key, 5  AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1008 AS apt_Key, 13 AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1009 AS apt_Key, 10 AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1010 AS apt_Key, 13 AS rate, 130 AS building FROM dual UNION ALL
  SELECT 1011 AS apt_Key, 8  AS rate, 130 AS building FROM dual
) /* END rates CTE */

/* Use the below to extract the min/max values per Group aka Building in this case */
, building_min_max AS
(
SELECT building, MIN(rate) AS min_rate, MAX(rate) AS max_rate, ROUND(AVG(rate), 1) AS avg_rate
FROM rates
GROUP BY building
)

/* Using a Detailed view mark each max and min rate so we can sum the up later */
SELECT COUNT(apt_key) AS tot_apts, r.building
  , ROUND(AVG(rate), 1) AS avg_rate
  , MIN(rate) AS min_rate
  , MAX(rate) AS max_rate
  , SUM(CASE WHEN r.rate = mm.min_rate THEN 1 ELSE 0 END) AS tot_min_rates
  , SUM(CASE WHEN r.rate = mm.max_rate THEN 1 ELSE 0 END) AS tot_max_rates
FROM rates r
  JOIN building_min_max mm ON mm.building = r.building
GROUP BY r.building
;

enter image description here