Oracle - Как показать общее количество [квартир] с минимальной / максимальной скоростью (проблема с вложенными агрегатными функциями) - PullRequest
0 голосов
/ 27 апреля 2019

Я хочу открыть для себя самый простой / наименее интенсивный подход, чтобы показать в строке данных, сколько записей в группе соответствует минимальным / максимальным показателям в данных, которые группируются. В моем примере здания сгруппированы.

В псевдокоде, который я предоставил, наряду с существующими столбцами, я также хочу предоставить еще два столбца, которые показывают, сколько квартир в каждом здании имеют ставки, которые соответствуют минимальным / максимальным ставкам в каждом здании. Интуитивно я думал, что все, что мне нужно было сделать, это подсчитать каждый случай, когда стоимость квартиры соответствовала минимальному / максимальному уровню группы. Проблема в том, что я сейчас вкладываю агрегатные функции, а это не получается. Возможно, я упускаю что-то простое.

В этой версии запроса (псевдокод намного проще моего реального кода) я мог бы просто обернуть запрос и затем использовать значения Мин / Макс для сравнения с уличными ставками во внешнем запросе, но я ищу простой подход, возможно, такой же простой, как мой псевдокод, если бы я мог вкладывать MIN (скорость) в 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 голосов
/ 29 апреля 2019

Из того, что я могу сказать, просто нет способа заставить это работать в одном и том же простом запросе без использования вложенных выборок, виртуальных таблиц или CTE. Попытка сделать скорость = МАКС (скорость) просто не распознается SQL. Из того, что я могу сказать, никакой движок базы данных не играет хорошо, когда вы пытаетесь это сделать. Облом.

Ссылка ниже, которую я нашел, предназначена для MS ACCESS, но это та же проблема.

Использование SQL для отображения количества мин и количества макс в группе

Хотя решение по приведенной выше ссылке работает, я предпочитаю удобство чтения и повторного использования общих табличных выражений (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

...