Как динамически выбирать столбцы в Oracle? Это возможно? - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть следующий набор данных:

NAME     2012        2013       2014         2015        2016         2017      2018         2019
JOHN      180          185       192          205         199          198       193          null
MIKE      190          191       191          195         195          null       195          195

В настоящее время у меня есть следующий запрос:

SELECT
    GREATEST(COALESCE("2019", 0),
             COALESCE("2018", 0),
             COALESCE("2017", 0),
             COALESCE("2016", 0),
             COALESCE("2015", 0),
             COALESCE("2014", 0),
             COALESCE("2013", 0),
             COALESCE("2012", 0)) AS max_weight
   , LEAST  (COALESCE("2019", 0),
             COALESCE("2018", 0),
             COALESCE("2017", 0),
             COALESCE("2016", 0),
             COALESCE("2015", 0),
             COALESCE("2014", 0),
             COALESCE("2013", 0),
             COALESCE("2012", 0)) AS max_weight
   , PERSON_NAME
  FROM yourTable;

Есть ли способ изменить вышеуказанный запрос так, чтобы он запрашивалтребуемый год, использует его в качестве входного параметра и получает только данные за этот частичный год + за 5 лет до этого?

Так, например: если я ввел 2017 год, он вернет следующий результат:

  PERSON_NAME         MIN_WEIGHT           MAX_WEIGHT
   JOHN                  185                  205
   MIKE                  190                  195

Есть ли способ сделать это? (похоже на параметр в функции / хранимой процедуре)? Я думал заменить год # каким-то параметром и ввести это ...

Заранее спасибо.

1 Ответ

3 голосов
/ 08 ноября 2019

Вы можете UNPIVOT свои столбцы в строки, чтобы вы могли применять к ним агрегаты, такие как MAX.

Примерно так:

with test_data (NAME, "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019" ) AS (
SELECT 'JOHN', 180, 185, 192, 205, 199, 198, 193, null FROM DUAL UNION ALL
SELECT 'MIKE', 190, 191, 191, 195, 195, null, 195, 195 FROM DUAL )
SELECT * 
FROM test_data
UNPIVOT ( 
  weight FOR year IN ("2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019")
);
+------+------+--------+
| NAME | YEAR | WEIGHT |
+------+------+--------+
| JOHN | 2012 |    180 |
| JOHN | 2013 |    185 |
| JOHN | 2014 |    192 |
| JOHN | 2015 |    205 |
| JOHN | 2016 |    199 |
| JOHN | 2017 |    198 |
| JOHN | 2018 |    193 |
| MIKE | 2012 |    190 |
| MIKE | 2013 |    191 |
| MIKE | 2014 |    191 |
| MIKE | 2015 |    195 |
| MIKE | 2016 |    195 |
| MIKE | 2018 |    195 |
| MIKE | 2019 |    195 |
+------+------+--------+

После того, как вы получили данные, которые не были развернуты таким образом, вы можете использовать агрегатные функции и GROUP BY, чтобы получить результаты, которые вы ищете:

with test_data (NAME, "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019" ) AS (
SELECT 'JOHN', 180, 185, 192, 205, 199, 198, 193, null FROM DUAL UNION ALL
SELECT 'MIKE', 190, 191, 191, 195, 195, null, 195, 195 FROM DUAL )
SELECT name, 
       min(weight) min_weight,
       max(weight) max_weight, 
       max(year) keep ( dense_rank last order by weight desc, year asc ) min_weight_year,
       max(year) keep ( dense_rank first order by weight desc, year asc ) max_weight_year
FROM test_data
UNPIVOT ( 
  weight FOR year IN ("2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019")
)
GROUP BY name;
+------+------------+------------+-----------------+-----------------+
| NAME | MIN_WEIGHT | MAX_WEIGHT | MIN_WEIGHT_YEAR | MAX_WEIGHT_YEAR |
+------+------------+------------+-----------------+-----------------+
| JOHN |        180 |        205 |            2012 |            2015 |
| MIKE |        190 |        195 |            2012 |            2015 |
+------+------------+------------+-----------------+-----------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...