Любой, кто работал с SQL, знает, какие отношения любовь-ненависть с ним связаны. SQL — мощный, стандартизированный и выразительный язык, но он также является одним из самых неинтуитивных языков для чтения и поддержки в масштабе. Чем глубже становится ваш запрос, тем труднее становится понять, что на самом деле происходит и в каком порядке.
Это потому, что SQL выполняется не в том порядке, в котором вы думаете. Вы начинаете с написания SELECTно база данных не обрабатывает его сначала. Двигатель запускается с FROM предложение, затем объединяет данные, фильтрует их, агрегирует и только позже применяет сортировку и проекцию. Результатом является письменный запрос. назад относительно способа его исполнения.
Это несоответствие между синтаксисом и выполнением делает SQL как когнитивно тяжелым, так и вычислительно дорогим. Аналитики часто полагаются на подзапросы или общие табличные выражения (CTE) для моделирования нисходящего потока, что создает ненужную сложность и дублирование. Даже опытные пользователи отлаживают вложенные логические блоки вместо того, чтобы сосредоточиться на проблеме, которую они решают.
Чтобы предотвратить это, BigQuery поддерживает синтаксис канала (|>)Эволюция SQL, который строит запросывыполняются в том же порядке, в котором они читаются. Вместо того, чтобы писать логику изнутри, вы пишете ее шаг за шагом, как конвейер данных — каждая строка представляет собой определенное преобразование. В результате получается SQL, который легче понять, легче отлаживать и который гораздо более интуитивно понятен для современного анализа данных.
На изображении выше показана основная проблема, которую решает синтаксис канала. В традиционном SQL синтаксический порядок (как вы пишете запрос) неправильно сопоставляется с смысловая последовательность (как база данных на самом деле обрабатывает это). Например, SELECT появляется вверху, но не оценивается движком до завершения фильтрации, группировки и сортировки. 
Эта последовательность представляет собой логический и синтаксический поток запроса конвейера BigQuery — сверху вниз и слева направо — показывая, как база данных фактически обрабатывает данные.
- ОТ: Отправная точка для любого запроса канала. Определяет исходную таблицу или подзапрос, из которого передаются данные. В синтаксисе канала 
FROMможет выступать отдельно в качестве допустимого запроса и действовать как запись в последовательном конвейере. - ПРИСОЕДИНИТЬСЯ: Расширяет текущую таблицу дополнительными столбцами и строками из другой таблицы или подзапроса. Можно использовать несколько раз подряд(
|> JOIN table USING (key)), что делает деревья глубоких соединений слева читабельными без вложенных подзапросов. - НАСТРАИВАТЬ: Обновляет существующие значения столбца вместо (
|> SET column = expression). Такие функции, какSELECT * REPLACE(...)стандартный SQL, но он более читабелен и модульен при использовании в качестве конвейерной операции. - ПРОДЛЕВАТЬ: Добавляет вычисляемые столбцы в существующий набор данных (
|> EXTEND expression AS new_column). Подобно SELECT *, new_column в стандартном SQL, но позволяет постепенно создавать производные поля между другими операциями, такими как соединения и фильтры. - УРОНИТЬ: Удаляет один или несколько столбцов из текущего набора данных (
|> DROP column_name). ЭквивалентSELECT * EXCEPT(column)стандартный SQL и часто используется для упрощения вывода или уменьшения размера промежуточных данных. - ГДЕ: Фильтрует строки, соответствующие условию (
|> WHERE condition). Может появляться где угодно до или после агрегирования, что устраняет необходимость использования разных ключевых слов, таких как HAVING или QUALIFY. - АГРЕГАТ: Выполняет полные табличные или сгруппированные сводки (
|> AGGREGATE SUM(column) AS total GROUP BY category). Заменяет GROUP BY и объединяет функции SELECT, упрощая синтаксис и приводя его в соответствие с логической последовательностью операций. - ЗАКАЗ: Сортировать строки по возрастанию или убыванию (
|> ORDER BY column DESC). Создает упорядоченную таблицу результатов, за которой могут следовать такие операторы, какLIMIT. - ОГРАНИЧЕНИЯ: Ограничить количество строк в результате (
|> LIMIT 10). Работает послеORDER BYили к неупорядоченным таблицам, сохраняя естественный порядок фильтров и агрегатов. - ЗВОНКИ: Запускает табличную функцию или модель машинного обучения, используя текущую таблицу в качестве входных данных (
|> CALL ML.PREDICT(MODEL project.model_name)). Устраняет необходимость во вложенных вызовах функций, создавая линейный и удобочитаемый рабочий процесс. - ВЫБИРАТЬ: Указывает окончательную проекцию столбца, включаемую в выходные данные (
|> SELECT column1, column2). Служит операцией закрытия трубопровода, аналогично операции терминала.SELECTв стандартном SQL-запросе. 
Ниже приведены наиболее распространенные сценарии, в которых синтаксис канала упрощает логику SQL, делая запросы более понятными и быстрыми в использовании.
Содержание
Агрегация данных без подзапросов
Агрегации — это то место, где SQL начинает чувствовать себя внутренним. Если хочешь что-то посчитать, то посчитай эти цифры, ты вдруг в скобках попадешь в ад.
SQL
SELECT c_count, COUNT(*) AS custdist
FROM (
  SELECT c_custkey, COUNT(o_orderkey) AS c_count
  FROM customer
  JOIN orders ON c_custkey = o_custkey
  WHERE o_comment NOT LIKE '%unusual%packages%'
  GROUP BY c_custkey
)
GROUP BY c_count
ORDER BY custdist DESC; Синтаксис канала
FROM customer
|> JOIN orders ON c_custkey = o_custkey
   AND o_comment NOT LIKE '%unusual%packages%'
|> AGGREGATE COUNT(o_orderkey) AS c_count GROUP BY c_custkey
|> AGGREGATE COUNT(*) AS custdist GROUP BY c_count
|> ORDER BY custdist DESC; Больше никакой вложенности или двойной группировки. Каждый шаг протекает логично и может быть изменен независимо, не переписывая весь запрос.
Очистка и преобразование колонны шаг за шагом
Если вам нужно писать строчные буквы, подсчитывать итоги и отбрасывать лишние столбцы, стандартный SQL заставляет переписать несколько SELECT уведомления. Знакомит с синтаксисом каналов SET, EXTENDи DROP операторы, чтобы изменения можно было применять последовательно.
SQL
SELECT o_custkey, ROUND(o_totalprice) AS total_price
FROM (
  SELECT
    o_custkey,
    o_totalprice,
    LOWER(o_orderstatus) AS o_orderstatus
  FROM orders
)
WHERE total_price > 1000; Синтаксис канала
FROM orders
|> SET o_orderstatus = LOWER(o_orderstatus)
|> EXTEND ROUND(o_totalprice) AS total_price
|> WHERE total_price > 1000
|> SELECT o_custkey, total_price; Каждая операция основывается на предыдущей, что упрощает отслеживание преобразований и повторное использование логики.
Фильтрация после агрегации без запоминания «IS»
Одна из особенностей SQL заключается в том, что время работы фильтров зависит от предложения. ты используешь WHERE перед группировкой и HAVING после, но на самом деле оба просто фильтруют строки. Синтаксис канала позволяет использовать WHERE последовательный, независимо от того, где вы его положили.
SQL
SELECT department, COUNT(*) AS emp_count
FROM employees
WHERE active = TRUE
GROUP BY department
HAVING COUNT(*) > 5; Синтаксис канала
FROM employees
|> WHERE active = TRUE
|> AGGREGATE COUNT(*) AS emp_count GROUP BY department
|> WHERE emp_count > 5; Теперь вы можете писать фильтры в том же порядке, в котором вы их себе представляете: сначала фильтруйте данные, затем группируйте их, а затем снова фильтруйте по результатам.
Отладка запросов без временных таблиц
Стандартный SQL требует от вас создания временной таблицы или заключения кода в несколько CTE для проверки промежуточного результата. Используя синтаксис канала, вы можете выполнить запрос к любой точке конвейера.
SQL
WITH filtered AS (
  SELECT * FROM orders WHERE o_totalprice > 500
),
summed AS (
  SELECT o_custkey, SUM(o_totalprice) AS total
  FROM filtered GROUP BY o_custkey
)
SELECT * FROM summed WHERE total > 10000; Синтаксис канала
FROM orders
|> WHERE o_totalprice > 500
|> AGGREGATE SUM(o_totalprice) AS total GROUP BY o_custkey
|> WHERE total > 10000; Каждый префикс запроса является индивидуально исполняемым, то есть вы можете «заглянуть» в данные на любом этапе. Это более чистый и интерактивный способ отладки и итерации.
Объединение моделей и функций без вложения
При работе с табличными функциями или моделями BigQuery ML вложение может быстро стать нечитаемым. Синтаксис канала заменяет эти вложенные вызовы линейной цепочкой с использованием CALL.
SQL
SELECT *
FROM ML.PREDICT(
  MODEL `project.sentiment_model`,
  (SELECT text FROM reviews)
); Синтаксис канала
SELECT text FROM reviews
|> CALL ML.PREDICT(MODEL `project.sentiment_model`); Если вы используете несколько моделей или преобразований, просто добавьте дополнительные строки CALL — скобки не требуются.
Изменение данных без вложенного выбора
Сведение данных всегда было утомительным процессом, часто требующим выполнения нескольких уровней подзапросов. Синтаксис канала упрощает это до одной плавной последовательности.
SQL
SELECT *
FROM (
  SELECT n_name, c_acctbal, c_mktsegment
  FROM customer JOIN nation USING (n_nationkey)
)
PIVOT(SUM(c_acctbal) FOR n_name IN ('PERU', 'KENYA', 'JAPAN')); Синтаксис канала
FROM customer
|> JOIN nation USING (n_nationkey)
|> SELECT n_name, c_acctbal, c_mktsegment
|> PIVOT(SUM(c_acctbal) FOR n_name IN ('PERU', 'KENYA', 'JAPAN')); Теперь запрос читается как рассказ: начните с данных, соедините их, выберите то, что вы хотите, затем поверните это.
Почему синтаксис канала меняет правила игры
Синтаксис канала не изобретает SQL заново, а совершенствует его. Он сохраняет всю мощь SQL в декларативной структуре, но устраняет когнитивные издержки, связанные с написанием логики задом наперед.
Для специалистов по данным, аналитиков и инженеров это означает:
- Легче читать, писать и отлаживать запросы.
 - Больше не нужно жонглировать подзапросами или простыми задачами CTE.
 - Оптимизированная логика, которая отражает то, как вы на самом деле думаете
 - Лучшая производительность и меньше лишних шагов
 
Синтаксис канала BigQuery — это SQL для современной эпохи данных: линейный, интуитивно понятный и оптимизированный для реального анализа.

