Количество подгрупп сводной таблицы SQL

#sql #oracle #pivot-table

#sql #Oracle #сводная таблица

Вопрос:

Я использую oracle для написания запроса, чтобы получить номер каждого жанра фильма за каждый год, но я сталкиваюсь с двумя проблемами:

  1. Если я хочу добавить новый столбец с именем before2015, который суммирует количество фильмов, снятых до 2015 года в каждом жанре, как я могу это сделать? Я пробовал в decode, но, похоже, он может идентифицировать только фактические слова, такие как 2015, вместо выражения <2015

  2. В приведенном ниже жанре существует много типов классической научной фантастики, если я хочу объединить все классические типы в один ряд, вместо классики, классической драмы, классического романа, классической войны. Как я могу этого добиться?

     SQL> select decode(genre,null,'Year Total',genre) genre,
      2     sum(decode (year, 2015, 1, 0)) Year2015,
      3     sum(decode (year, 2016, 1, 0)) Year2016,
      4     sum(decode (year, 2017, 1, 0)) Year2017
      5  from film
      6  group by rollup(genre);
    
    GENRE                       YEAR2015   YEAR2016   YEAR2017
    ------------------------- ---------- ---------- ----------
    Action and Adventure               1          1          0
    Children and Family                0          1          1
    Classic                            0          0          0
    Classic, Drama                     0          0          0
    Classic, Romance                   0          0          0
    Classic, War                       0          0          0
    Comedy                             0          0          0
    Documentary                        0          0          0
    Fantasy                            1          0          0
    Sci-Fi                             0          2          1
    TV Drama                           2          0          1
    TV Sci-Fi                          0          0          0
    Thriller                           0          0          0
    War                                0          0          0
    Year Total                         4          4          3
      

Редактировать
вот пример данных:

 INSERT INTO film VALUES ('11W', 'Wide Screen', 'Gone with the Wind', 1939, 2, null, 233, 'Romance');
INSERT INTO film VALUES ('12F', 'Full Screen', 'The Longest Day', 1962, 1, null, 178, 'War');
INSERT INTO film VALUES ('13F', 'Full Screen', 'Roman Holiday', 1953, 1, 'NR', 118, 'Classic');
INSERT INTO film VALUES ('14F', 'Full Screen', 'Sabrina', 1954, 1,'NR', 113, 'Classic');
INSERT INTO film VALUES ('15W', 'Wide Screen', 'Breakfast at Tiffany', 1961, 1, 'NR', 115, 'Classic');
INSERT INTO film VALUES ('16W', 'Wide Screen', 'My Fair Lady', 1964, 1, 'G', 172, NULL);
INSERT INTO film VALUES ('17F', 'Full Screen', 'The Heart is a Lonely Hunter', 1968, 1, null, 123, 'Drama');
INSERT INTO film VALUES ('23W', 'Full Screen', 'Titanic: The Complete Story', 1994, 2,'NR', 300, 'Documentary');
INSERT INTO film VALUES ('24F', 'Full Screen', 'Rush Hour', 1998, 1, 'PG-13', 98, 'Comedy');
INSERT INTO film VALUES ('28W', 'Wide Screen', 'Pearl Harbor', 2001, 1, 'PG-13', 183, 'War');
INSERT INTO film VALUES ('31W', 'Wide Screen', 'Avatar', 2010, 3,'PG-13', 162,'Sci-Fi');
INSERT INTO film VALUES ('38W', 'Wide Screen', 'Star Wars: The Force Awakens', 2016, 3,'PG-13', 136,'Sci-Fi');
INSERT INTO film VALUES ('40W', 'Wide Screen', 'Harry Potter and the Deathly Hollows: Part I', 2011, 1, 'PG-13', 146, 'Fantasy');
INSERT INTO film VALUES ('41W', 'Multiple Formats', 'Transformers: Age of Extinction', 2014, 1,'PG-13', 164,'Action and Adventure');
INSERT INTO film VALUES ('42F', 'Wide Screen', 'Horrible Bosses', 2011, 1, 'R', 98, 'Comedy');
INSERT INTO film VALUES ('43W', 'Wide Screen', 'Rogue One: A Star Wars Story', 2017, 3,'PG-13', 133,'Sci-Fi');
INSERT INTO film VALUES ('44W', 'Wide Screen', 'The Prince of Persia: The Sands of Time', 2010, 1,'PG-13', 116, 'Action and Adventure');
INSERT INTO film VALUES ('45W', 'Wide Screen', 'Clash of the Titans', 2010, 1,'PG-13', 106, 'Action and Adventure');
INSERT INTO film VALUES ('46W', 'Wide Screen', 'Skyfall', 2012, 1, 'PG-13', 143, 'Action and Adventure');
INSERT INTO film VALUES ('47W', 'Wide Screen', 'Hugo', 2012, 1,'PG', 126,'Children and Family');
INSERT INTO film VALUES ('48W', 'Wide Screen', 'Brave', 2012, 1, 'PG', 93, 'Children and Family');
INSERT INTO film VALUES ('49W', 'Wide Screen', 'Zootopia', 2016, 1,'PG', 108,'Children and Family');
INSERT INTO film VALUES ('50W', 'Wide Screen', 'Star Trek', 2010, 1, 'PG-13', 127, 'Sci-Fi');
INSERT INTO film VALUES ('60W', 'Wide Screen', 'Harry Potter and the Deathly Hollows: Part II', 2012, 1, 'PG-13', 130, 'Fantasy');
INSERT INTO film VALUES ('61W', 'Multiple Formats', 'Guardians of the Galaxy', 2014, 1, 'PG-13', 121, 'Sci-Fi');
INSERT INTO film VALUES ('62W', 'Wide Screen', 'Alphas: Season 1', 2012, 3,'NR', 497,'TV Sci-Fi');
INSERT INTO film VALUES ('63W', 'Wide Screen', 'The Dark Knight Rises', 2012, 1, 'PG-13', 165, 'Action and Adventure');
INSERT INTO film VALUES ('64W', 'Wide Screen', 'The Avengers', 2012, 1, 'PG-13', 143, 'Action and Adventure');
INSERT INTO film VALUES ('65W', 'Wide Screen', 'Wrath of the Titans', 2012, 1, 'PG-13', 99, 'Action and Adventure');
INSERT INTO film VALUES ('66W', 'Multiple Formats', 'Scorpion: Season 1', 2015, 6,'NR', 916,'TV Drama');
INSERT INTO film VALUES ('67W', 'Wide Screen', 'Spectre', 2016, 1, 'PG-13', 150, 'Action and Adventure');
INSERT INTO film VALUES ('68W', 'Wide Screen', 'Alphas: Season 2', 2013, 3,'NR', 562,'TV Sci-Fi');
INSERT INTO film VALUES ('71W', 'Wide Screen', 'The Croods', 2013, 1, 'PG', 96, 'Children and Family');
INSERT INTO film VALUES ('72W', 'Wide Screen', 'Moana', 2017, 1,'PG', 107,'Children and Family');
INSERT INTO film VALUES ('73W', 'Wide Screen', 'A Good Day to Die Hard', 2013, 1, 'R', 97, 'Thriller');
INSERT INTO film VALUES ('74W', 'Wide Screen', 'Star Trek: Into Darkness', 2013, 1, 'PG-13', 132, 'Sci-Fi');
INSERT INTO film VALUES ('80W','Wide Screen', 'The Hunger Game: Catching Fire', 2014, 1,'PG-13', 146,'Sci-Fi');
INSERT INTO film VALUES ('81W','Wide Screen', 'The Hobbit: The Desolation of Smaug', 2014, 2,'PG-13', 161,'Fantasy');
INSERT INTO film VALUES ('82W','Wide Screen', 'The Hobbit: The Battle of the Five Armies', 2015, 2,'PG-13', 144,'Fantasy');
INSERT INTO film VALUES ('83W','Wide Screen', 'Lucy', 2015, 2,'R', 90,'Action and Adventure');
INSERT INTO film VALUES ('84M','Multiple Formats', 'Star Trek Beyond',2016,2,'PG-13',122,'Sci-Fi');
  

Комментарии:

1. Пожалуйста, добавьте некоторые примеры данных.

2. Я добавил это, спасибо.

Ответ №1:

Вы можете использовать sign() ( расшифровывается signum в математике) функцию для получения нужного столбца :

 sum(decode (sign(year - 2015), -1 , 1, 0)) as Before2015
  

и вы можете использовать этот запрос

 select decode(substr(genre,1,7),'Classic','Classic',genre),
       sum(decode (sign(year - 2015), -1 , 1, 0)) as Before2015,
       sum(decode (year, 2015, 1, 0)) Year2015,
       sum(decode (year, 2016, 1, 0)) Year2016,
       sum(decode (year, 2017, 1, 0)) Year2017
  from film
 group by rollup(decode(substr(genre,1,7),'Classic','Classic',genre))
  

чтобы объединить все Classic жанровые фильмы.

Комментарии:

1. @ShinYuWu конечно, вам нужен decode or case..when для таких дополнительных случаев. Для ‘Sci-Fi’ вам нужна regex substr-instr операция or также для извлечения из строки жанра, поскольку это не в начале, как Classic .