使用萬用字元資料表查詢多個資料表

萬用字元資料表可讓您使用精簡的 SQL 陳述式查詢多個資料表。萬用字元表格僅在 GoogleSQL 中提供。如要在舊版 SQL 中使用對應的功能,請參閱資料表萬用字元函式

萬用字元資料表是符合萬用字元運算式的所有資料表的集合。舉例來說,下列 FROM 子句使用萬用字元運算式 gsod*,比對 noaa_gsod 資料集中開頭為字串 gsod 的所有資料表。

FROM
  `bigquery-public-data.noaa_gsod.gsod*`

萬用字元資料表中的每一列都包含一個特殊資料欄 _TABLE_SUFFIX,當中有經萬用字元比對後所得出的值。

限制

萬用字元資料表查詢有下列限制。

  • 萬用字元表格功能不支援檢視畫面。如果萬用字元資料表與資料集中的任何檢視表相符,即使查詢在 _TABLE_SUFFIX 虛擬資料欄上加入 WHERE 子句來篩除檢視表,查詢仍會傳回錯誤。
  • 使用萬用字元查詢多個資料表時,無法使用快取結果,即使已勾選「Use Cached Results」選項也是如此。如果您執行相同的萬用字元查詢很多次,系統會針對每一筆查詢向您收費。
  • 萬用字元資料表僅支援內建的 BigQuery 儲存空間。您無法使用萬用字元查詢外部資料表檢視表
  • 您無法在分區不相容的資料表或分區和非分區資料表混合使用萬用字元查詢。查詢的資料表也必須具有相同的分群規格。
  • 您可以將萬用字元資料表與分區資料表搭配使用,且系統支援分區修剪和叢集修剪。不過,已分組但未分區的資料表無法充分利用萬用字元,因此無法獲得叢集裁剪功能的全部優勢。
  • 包含資料操縱語言 (DML) 陳述式的查詢,無法使用萬用字元資料表做為查詢目標。例如,可在 UPDATE 查詢的 FROM 子句中使用萬用字元資料表,但無法將萬用字元資料表做為 UPDATE 運算的目標。
  • 在包含 JavaScript 使用者定義函式的 _TABLE_SUFFIX_PARTITIONTIME 虛擬欄上設定篩選器,不會限制萬用字元資料表中掃描的資料表數量。
  • 以客戶管理的加密金鑰 (CMEK) 保護的資料表不支援萬用字元查詢。
  • 在萬用字元查詢中參照的所有資料表,都必須具備完全相同的標記鍵和值。
  • 使用萬用字元資料表時,即使 _TABLE_SUFFIXREGEXP_CONTAINS 搭配使用,並提供 ^[0-9]{2}$ 等規則運算式,資料集中以 * 之前的資料表名稱開頭的所有資料表都會掃描。例如:

    SELECT *
    FROM `my_project.my_dataset.my_table_*`
    WHERE REGEXP_CONTAINS(_TABLE_SUFFIX, '^[0-9]{2}$');
    
  • 如果單一掃描的資料表有結構定義不相符的情況 (也就是具有相同名稱的資料欄屬於不同類型),查詢就會失敗,並顯示「Cannot read field of type X as Y Field: column_name」錯誤訊息。即使您使用相等運算子 =,系統也會比對所有資料表。例如,在下列查詢中,系統也會掃描資料表 my_dataset.my_table_03_backup。因此,查詢可能會因結構定義不相符而失敗。不過,如果沒有架構不相符的情況,結果就會如預期,只來自資料表 my_dataset.my_table_03

    SELECT *
    FROM my_project.my_dataset.my_table_*
    WHERE _TABLE_SUFFIX = '03'
    

事前準備

使用萬用字元表格的時機

如果資料集包含多個名稱類似且具有相容結構定義的資料表,就很適合使用萬用字元資料表。一般來說,這類資料集所包含的每一個資料表都分別代表單日、單月或單一年度的資料。舉例來說,BigQuery 所託管的公開資料集 NOAA 全球每日地面天氣摘要資料包含許多資料表,分別代表 1929 年至今每一年的資料。

執行查詢以掃描 1929 年到 1940 年之間所有的資料表 ID 時,如果要在 FROM 子句中指定所有 12 個資料表,查詢會變得相當冗長 (以下範例已省略大部分的資料表):

#standardSQL
SELECT
  max,
  ROUND((max-32)*5/9,1) celsius,
  mo,
  da,
  year
FROM (
  SELECT
    *
  FROM
    `bigquery-public-data.noaa_gsod.gsod1929` UNION ALL
  SELECT
    *
  FROM
    `bigquery-public-data.noaa_gsod.gsod1930` UNION ALL
  SELECT
    *
  FROM
    `bigquery-public-data.noaa_gsod.gsod1931` UNION ALL

  # ... Tables omitted for brevity

  SELECT
    *
  FROM
    `bigquery-public-data.noaa_gsod.gsod1940` )
WHERE
  max != 9999.9 # code for missing data
ORDER BY
  max DESC

如果使用萬用字元資料表,同一個查詢會變得精簡許多:

#standardSQL
SELECT
  max,
  ROUND((max-32)*5/9,1) celsius,
  mo,
  da,
  year
FROM
  `bigquery-public-data.noaa_gsod.gsod19*`
WHERE
  max != 9999.9 # code for missing data
  AND _TABLE_SUFFIX BETWEEN '29'
  AND '40'
ORDER BY
  max DESC
萬用字元資料表僅支援內建的 BigQuery 儲存空間。查詢外部資料表檢視表時,不可以使用萬用字元。

萬用字元資料表語法

萬用字元資料表語法:

SELECT
FROM
  `<project-id>.<dataset-id>.<table-prefix>*`
WHERE
  bool_expression
<project-id>
Cloud Platform 專案 ID。如果您使用預設專案 ID,則為選用項目。
<dataset-id>
BigQuery 資料集 ID。
<table-prefix>
萬用字元比對後,所有資料表都會共用這個字串。資料表前置字串可省略,省略資料表前置字串會比對資料集中的所有資料表。
* (萬用字元)
萬用字元「*」代表資料表名稱的一或多個字元。萬用字元只能出現在萬用字元資料表名稱的最後一個字元。

含有萬用字元資料表的查詢支援 WHERE 子句中的 _TABLE_SUFFIX 虛擬欄。這個資料欄包含萬用字元所比對的值,因此查詢可以篩選要存取的資料表。舉例來說,下列 WHERE 子句使用比較運算子篩選相符的資料表:

WHERE
  _TABLE_SUFFIX BETWEEN '29' AND '40'

WHERE
  _TABLE_SUFFIX = '1929'

WHERE
  _TABLE_SUFFIX < '1941'

如要進一步瞭解 _TABLE_SUFFIX 虛擬資料欄,請參閱「使用 _TABLE_SUFFIX 篩選所選資料表」一節。

在倒引號中以萬用字元括住資料表名稱

萬用字元資料表名稱包含特殊字元 (*),這代表您必須將萬用字元資料表名稱括在倒引號 (`) 字元內。舉例來說,以下查詢使用了倒引號,屬於有效的查詢:

#standardSQL
/* Valid SQL query */
SELECT
  max
FROM
  `bigquery-public-data.noaa_gsod.gsod*`
WHERE
  max != 9999.9 # code for missing data
  AND _TABLE_SUFFIX = '1929'
ORDER BY
  max DESC

以下查詢因沒有正確使用倒引號而「無效」:

#standardSQL
/* Syntax error: Expected end of statement but got "-" at [4:11] */
SELECT
  max
FROM
  # missing backticks
  bigquery-public-data.noaa_gsod.gsod*
WHERE
  max != 9999.9 # code for missing data
  AND _TABLE_SUFFIX = '1929'
ORDER BY
  max DESC

引號無法運作:

#standardSQL
/* Syntax error: Unexpected string literal: 'bigquery-public-data.noaa_gsod.gsod*' at [4:3] */
SELECT
  max
FROM
  # quotes are not backticks
  'bigquery-public-data.noaa_gsod.gsod*'
WHERE
  max != 9999.9 # code for missing data
  AND _TABLE_SUFFIX = '1929'
ORDER BY
  max DESC

使用萬用字元資料表查詢資料表

萬用字元表格可讓您以精簡的方式查詢多個表格。舉例來說,BigQuery 所託管的公開資料集 NOAA 全球每日地面天氣摘要資料包含許多資料表,分別代表 1929 年至今每一年的資料,而且全都共用相同的前置字串 gsod,後面加上四位數的年份,資料表名稱分別為 gsod1929gsod1930gsod1931 等。

如要查詢一組前置字元都相同的資料表,請在 FROM 陳述式中的資料表前置字元後方加上資料表萬用字元符號 (*)。舉例來說,以下查詢會找出 1940 年代期間所回報的最高氣溫:

#standardSQL
SELECT
  max,
  ROUND((max-32)*5/9,1) celsius,
  mo,
  da,
  year
FROM
  `bigquery-public-data.noaa_gsod.gsod194*`
WHERE
  max != 9999.9 # code for missing data
ORDER BY
  max DESC

使用 _TABLE_SUFFIX 篩選所選資料表

如要限制查詢,讓其只掃描特定的資料表組,請在 WHERE 子句中使用 _TABLE_SUFFIX 虛擬資料欄,並加上常數運算式的條件。

_TABLE_SUFFIX 虛設欄包含表格萬用字元比對後的值。舉例來說,先前的查詢範例會掃描 1940 年代的所有資料表,並使用表格萬用字元代表年份的最後一個數字:

FROM
  `bigquery-public-data.noaa_gsod.gsod194*`

對應的 _TABLE_SUFFIX 虛擬欄包含 09 範圍的值,代表 gsod1940gsod1949 的資料表。這些 _TABLE_SUFFIX 值可用於 WHERE 子句,用來篩選特定資料表。

舉例來說,如要篩選出 1940 年到 1944 年之間的最高氣溫,請使用 04 來做為 _TABLE_SUFFIX 的值:

#standardSQL
SELECT
  max,
  ROUND((max-32)*5/9,1) celsius,
  mo,
  da,
  year
FROM
  `bigquery-public-data.noaa_gsod.gsod194*`
WHERE
  max != 9999.9 # code for missing data
  AND ( _TABLE_SUFFIX = '0'
    OR _TABLE_SUFFIX = '4' )
ORDER BY
  max DESC

使用 _TABLE_SUFFIX 可大幅減少掃描的位元組數,有助於降低執行查詢的成本。

不過,如果 _TABLE_SUFFIX 上的篩選器包含沒有常數運算式的條件,就不會限制萬用字元資料表中掃描的資料表數量。舉例來說,下列查詢無法限制萬用字元資料表 bigquery-public-data.noaa_gsod.gsod19* 的掃描資料表數量,因為篩選器使用 table_id 資料欄的動態值:

#standardSQL
# Scans all tables that match the prefix `gsod19`
SELECT
  ROUND((max-32)*5/9,1) celsius
FROM
  `bigquery-public-data.noaa_gsod.gsod19*`
WHERE
  _TABLE_SUFFIX = (SELECT SUBSTR(MAX(table_name), LENGTH('gsod19') + 1)
      FROM `bigquery-public-data.noaa_gsod.INFORMATION_SCHEMA.TABLES`
      WHERE table_name LIKE 'gsod194%')

舉例來說,以下查詢會根據第一個篩選條件 _TABLE_SUFFIX BETWEEN '40' and '60' 限制掃描作業,因為這是常數運算式。不過,以下查詢不會根據第二個篩選條件 _TABLE_SUFFIX = (SELECT SUBSTR(MAX(table_name), LENGTH('gsod19') + 1) FROM bigquery-public-data.noaa_gsod.INFORMATION_SCHEMA.TABLES WHERE table_name LIKE 'gsod194%') 限制掃描作業,因為這是動態運算式:

#standardSQL
# Scans all tables with names that fall between `gsod1940` and `gsod1960`
SELECT
  ROUND((max-32)*5/9,1) celsius
FROM
  `bigquery-public-data.noaa_gsod.gsod19*`
WHERE
  _TABLE_SUFFIX BETWEEN '40' AND '60'
  AND _TABLE_SUFFIX = (SELECT SUBSTR(MAX(table_name), LENGTH('gsod19') + 1)
      FROM `bigquery-public-data.noaa_gsod.INFORMATION_SCHEMA.TABLES`
      WHERE table_name LIKE 'gsod194%')

解決方法是改為執行兩個不同的查詢,例如:

第一個查詢:

#standardSQL
# Get the list of tables that match the required table name prefixes
SELECT SUBSTR(MAX(table_name), LENGTH('gsod19') + 1)
      FROM `bigquery-public-data.noaa_gsod.INFORMATION_SCHEMA.TABLES`
      WHERE table_name LIKE 'gsod194%'

第二個查詢:

#standardSQL
# Construct the second query based on the values from the first query
SELECT
  ROUND((max-32)*5/9,1) celsius
FROM
  `bigquery-public-data.noaa_gsod.gsod19*`
WHERE _TABLE_SUFFIX = '49'

這些範例查詢會使用 INFORMATION_SCHEMA.TABLES 檢視畫面。如要進一步瞭解 INFORMATION_SCHEMA 資料表,請參閱「使用 INFORMATION_SCHEMA 取得資料表中繼資料」。

使用 _TABLE_SUFFIX 掃描特定範圍的資料表

如要掃描特定範圍的資料表,請使用 _TABLE_SUFFIX 虛擬資料欄和 BETWEEN 子句。舉例來說,如要找出 1929 年到 1935 年 (包含這兩年) 之間回報的最高氣溫,請使用資料表萬用字元來代表年份的最後兩位數字:

#standardSQL
SELECT
  max,
  ROUND((max-32)*5/9,1) celsius,
  mo,
  da,
  year
FROM
  `bigquery-public-data.noaa_gsod.gsod19*`
WHERE
  max != 9999.9 # code for missing data
  AND _TABLE_SUFFIX BETWEEN '29' and '35'
ORDER BY
  max DESC

使用 _PARTITIONTIME 掃描特定範圍的擷取時間分區資料表

如要掃描特定範圍的擷取時間分區資料表,請使用 _PARTITIONTIME 虛擬資料欄搭配 _TABLE_SUFFIX 虛擬資料欄。例如,以下查詢會掃描資料表 my_dataset.mytable_id1 中的 2017 年 1 月 1 日分區。

#standardSQL
SELECT
  field1,
  field2,
  field3
FROM
  `my_dataset.mytable_*`
WHERE
  _TABLE_SUFFIX = 'id1'
  AND _PARTITIONTIME = TIMESTAMP('2017-01-01')

查詢資料集中的所有資料表

如要掃描資料集中的所有資料表,您可以使用空白前置字元和資料表萬用字元,這表示 _TABLE_SUFFIX 虛擬資料欄包含完整的資料表名稱。舉例來說,下列 FROM 子句會掃描 GSOD 資料集中的所有資料表:

FROM
  `bigquery-public-data.noaa_gsod.*`

如果前置字元為空白,_TABLE_SUFFIX 虛擬資料欄會包含完整的資料表名稱。舉例來說,以下查詢與前述範例相同,都是找出 1929 年到 1935 年間的最高溫度,但在 WHERE 子句中使用完整的資料表名稱:

#standardSQL
SELECT
  max,
  ROUND((max-32)*5/9,1) celsius,
  mo,
  da,
  year
FROM
  `bigquery-public-data.noaa_gsod.*`
WHERE
  max != 9999.9 # code for missing data
  AND _TABLE_SUFFIX BETWEEN 'gsod1929' and 'gsod1935'
ORDER BY
  max DESC

不過請注意,前置字元越長通常成效越佳。詳情請參閱最佳做法部分。

查詢執行詳細資料

用於評估查詢作業的結構定義

為了執行使用萬用字元資料表的 GoogleSQL 查詢,BigQuery 會自動推論該資料表的結構定義。BigQuery 會將最近建立的資料表結構定義 (與萬用字元相符) 用作萬用字元資料表的結構定義。即使您使用 WHERE 子句中的 _TABLE_SUFFIX 虛擬資料欄,限制要從萬用字元資料表使用的資料表數量,BigQuery 仍會使用與萬用字元相符的最近建立資料表的結構定義。

如果推斷的結構定義中所含資料欄不在相符的資料表中,則 BigQuery 會針對該資料表缺少該資料欄的資料列,傳回該資料欄的 NULL 值。

如果萬用字元查詢比對的資料表結構定義不一致,BigQuery 會傳回錯誤。當相符資料表的資料欄具有不同的資料類型,或是無法假設在所有相符資料表中都沒有的資料欄具有空值時,就會發生這種情況。

最佳做法

  • 相較於較短的前置字元,較長的前置字元通常成效較佳。例如,以下查詢使用長前置字串 (gsod200):

    #standardSQL
    SELECT
    max
    FROM
    `bigquery-public-data.noaa_gsod.gsod200*`
    WHERE
    max != 9999.9 # code for missing data
    AND _TABLE_SUFFIX BETWEEN '0' AND '1'
    ORDER BY
    max DESC

    以下查詢使用了空白前置字元,因此通常成效較差:

    #standardSQL
    SELECT
    max
    FROM
    `bigquery-public-data.noaa_gsod.*`
    WHERE
    max != 9999.9 # code for missing data
    AND _TABLE_SUFFIX BETWEEN 'gsod2000' AND 'gsod2001'
    ORDER BY
    max DESC
  • 建議您使用分區功能,而非資料分割,因為分區資料表的效能較佳。分割會降低效能,同時也會產生更多需要管理的資料表。詳情請參閱「分區與分割」。

如要瞭解在 BigQuery 中控管費用的最佳做法,請參閱「在 BigQuery 中控管費用

後續步驟