SQL: создание столбцов из отдельных значений столбца.

Я пытаюсь сделать запрос, основанный на отдельном значении определенного столбца таблицы. Я использую сервис Bigquery из Google Cloud.

Вот как выглядит моя таблица:

Дата Тип Расположение Имя Группа 2022-07 Тип 1 Местоположение1 Имя1 Группа 1 2022-07 Тип2 Местоположение1 Имя2 Группа2 2022-08 Тип 1 Местоположение2 Имя3 Группа2 ... ... ... ... ...

Я хочу подсчитать количество каждого Type для каждого конкретного места. Проблема в том, что существует большое количество разных Type и Location.

Вот что я обычно делаю:

SELECT DISTINCT Location,
COUNT(DISTINCT CASE WHEN Type = Type1 THEN Name END),
COUNT(DISTINCT CASE WHEN Type = Type2 THEN Name END),
COUNT(DISTINCT CASE WHEN Type = Type3 THEN Name END),
... #same thing for all types
FROM `table`
WHERE Group = "Group1" OR Group = "Group2"
GROUP BY Location

Мне было интересно, есть ли способ получить все значения из столбца Type и выполнить итерацию для автоматического создания столбца без необходимости вручную вводить его, чтобы получить что-то вроде этого:

SELECT DISTINCT Location,
iterate on Type[n]
COUNT(DISTINCT CASE WHEN Type = Type[n] THEN Name END)
FROM `table`
WHERE Group = "Group1" OR Group = "Group2"
GROUP BY Location

Чтобы получить:

Расположение Тип 1 Тип2 Тип3 ... Местоположение1 n_Type1 n_Type2 n_Type3 ... Местоположение2 n_Type1 n_Type2 n_Type3 ... Местоположение3 n_Type1 n_Type2 n_Type3 ... ... ... ... ... ...

Я видел функцию PIVOT в других сообщениях, которую можно использовать для достижения желаемого результата, но я изо всех сил пытаюсь поставить ее на место, тем более что некоторые Type имеют пробелы, а это означает, что мне нужно использовать замену, чтобы они быть допустимыми именами столбцов.

Вот мой SQL-запрос с использованием PIVOT (не работает):

EXECUTE IMMEDIATE(SELECT '''
SELECT Location, REPLACE(Type, " ", "_") AS Type,
COUNT(Distinct Name) AS Nbr
FROM `table`
WHERE Group LIKE "Group1" 
OR Group LIKE "Group2"
GROUP BY Location,  Type
PIVOT (any_value(Result) for Type in (''' || string_agg(distinct "'" || REPLACE(Type, " ", "_") || "'") || 
"))"
FROM `table`
)

Заранее спасибо за ответ! Хорошего дня!

Так как некоторые типы имеют пробелы --> type1 и type 1 следует считать одинаковыми?

Jaytiger 21.02.2023 13:07

Нет, они разные

Hibann 21.02.2023 14:38
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
Как сделать движок для футбольного матча? (простой вариант)
Как сделать движок для футбольного матча? (простой вариант)
Футбол. Для многих людей, живущих на земле, эта игра - больше, чем просто спорт. И эти люди всегда мечтают стать футболистом или менеджером. Но, к...
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел "Заголовок" в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
0
2
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется, вам нужен агрегированный и сводной запрос.

1-й шаг: агрегация

SELECT Location, Type, COUNT(Name) Count 
  FROM sample_table 
 GROUP BY 1, 2;

Это возвращает сложенный (несвернутый) результат, как показано ниже.

2-й шаг: поворот

Как только вы повернете предыдущий результат, вы получите желаемый результат.

SELECT * FROM (
  SELECT Location, Type, COUNT(Name) Count 
    FROM sample_table 
   GROUP BY 1, 2
) PIVOT (ANY_VALUE(Count) FOR Type IN ('Type1', 'Type2', 'Type3'));

3-й шаг: динамический запрос

итерация по Type[n] COUNT (ОТЛИЧНЫЙ СЛУЧАЙ, КОГДА Тип = Тип [n], ТОГДА Имя КОНЕЦ)

Если n большое число, вам следует рассмотреть динамический запрос. вы можете обратиться к следующим ссылкам для этого.


Обновлено

CREATE TEMP TABLE `sample_table` AS
  SELECT '2022-07' Date, 'Type1' Type, 'Location1' Location, 'Name1' Name, 'Group1' `Group` UNION ALL
  SELECT '2022-07' Date, 'Type2' Type, 'Location1' Location, 'Name2' Name, 'Group2' `Group` UNION ALL
  SELECT '2022-08' Date, 'Type 1' Type, 'Location2' Location, 'Name3' Name, 'Group2' `Group`
;

-- before using a dynamic sql
SELECT * FROM (
  SELECT Location, REPLACE(Type, " ", "_") AS Type,
         COUNT(Distinct Name) AS Nbr
    FROM `sample_table`
   WHERE `Group` LIKE "Group1" OR `Group` LIKE "Group2"
   GROUP BY Location, Type
)  PIVOT (ANY_VALUE(Nbr) FOR Type IN ('Type1', 'Type2', 'Type_1'));

-- using a dynamic sql
EXECUTE IMMEDIATE FORMAT("""
SELECT * FROM (
  SELECT Location, REPLACE(Type, " ", "_") AS Type,
         COUNT(Distinct Name) AS Nbr
    FROM `sample_table`
   WHERE `Group` LIKE "Group1" OR `Group` LIKE "Group2"
   GROUP BY Location, Type
)  PIVOT (ANY_VALUE(Nbr) FOR Type IN ('%s'))
""", (SELECT STRING_AGG(DISTINCT REPLACE(Type, ' ', '_'), "','")
        FROM `sample_table`
       WHERE `Group` LIKE 'Group1' OR `Group` LIKE 'Group2'
     ));

Я пытаюсь выполнить эти шаги, но я борюсь с самой командой поворота, как вы сказали, она должна быть динамической, и для этого мне нужно использовать команду EXECUTE IMMEDIATE(). Я предполагаю, что проблема заключается в синтаксисе моего сводного запроса, но я пока не вижу ошибки.

Hibann 21.02.2023 14:44

Я проверил ваш ответ, я получаю сообщение об ошибке: «Недопустимый символ спецификатора формата «V» в строке FORMAT». Я вижу, что вы пытаетесь сделать с этим ответом, и я думаю, что это правильный подход, возможно, это ошибка моя сторона

Hibann 21.02.2023 15:42

Если вы запустите запрос как есть, он будет успешным, поэтому еще раз взгляните на свой код, а также проверьте данные, которые вы тестируете. и если вы по-прежнему получаете сообщение об ошибке, дайте мне знать с фактическим запросом, который вы тестируете.

Jaytiger 21.02.2023 15:50

Каким-либо изменением, вы используете % в своем запросе, например LIKE 'Group%' или что-то в этом роде?

Jaytiger 21.02.2023 15:52

Да, я для того, чтобы фильтровать группы по своему выбору, в обоих случаях

Hibann 21.02.2023 15:59

Если это так, вам нужно экранировать % с помощью дополнительной % в функции format(), см. здесь stackoverflow.com/questions/75397329/…

Jaytiger 21.02.2023 16:01

Отлично, побег с дополнительным % помог, спасибо за помощь

Hibann 21.02.2023 16:06

Другие вопросы по теме