Я пытаюсь сделать запрос, основанный на отдельном значении определенного столбца таблицы. Я использую сервис Bigquery из Google Cloud.
Вот как выглядит моя таблица:
Я хочу подсчитать количество каждого 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
Чтобы получить:
Я видел функцию 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`
)
Заранее спасибо за ответ! Хорошего дня!
Нет, они разные
Кажется, вам нужен агрегированный и сводной запрос.
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(). Я предполагаю, что проблема заключается в синтаксисе моего сводного запроса, но я пока не вижу ошибки.
Я проверил ваш ответ, я получаю сообщение об ошибке: «Недопустимый символ спецификатора формата «V» в строке FORMAT». Я вижу, что вы пытаетесь сделать с этим ответом, и я думаю, что это правильный подход, возможно, это ошибка моя сторона
Если вы запустите запрос как есть, он будет успешным, поэтому еще раз взгляните на свой код, а также проверьте данные, которые вы тестируете. и если вы по-прежнему получаете сообщение об ошибке, дайте мне знать с фактическим запросом, который вы тестируете.
каким-либо изменением, вы используете %
в своем запросе, например LIKE 'Group%'
или что-то в этом роде?
Да, я для того, чтобы фильтровать группы по своему выбору, в обоих случаях
Если это так, вам нужно экранировать %
с помощью дополнительной %
в функции format(), см. здесь stackoverflow.com/questions/75397329/…
Отлично, побег с дополнительным %
помог, спасибо за помощь
так как некоторые типы имеют пробелы -->
type1
иtype 1
следует считать одинаковыми?