Membuat kueri pada kolom bertingkat dan berulang di legacy SQL
Dokumen ini menjelaskan cara membuat kueri data bertingkat dan berulang dalam sintaksis kueri legacy SQL. Sintaksis kueri yang lebih disukai untuk BigQuery adalah GoogleSQL. Untuk informasi tentang penanganan data bertingkat dan berulang di GoogleSQL, lihat panduan migrasi GoogleSQL.
BigQuery mendukung pemuatan
dan ekspor data bertingkat dan berulang dalam
bentuk file JSON dan Avro. Untuk banyak kueri legacy SQL, BigQuery dapat meratakan data
secara otomatis. Misalnya, banyak pernyataan SELECT
dapat mengambil kolom bertingkat atau berulang
sekaligus mempertahankan struktur data, dan klausa WHERE
dapat memfilter data
sekaligus mempertahankan strukturnya. Sebaliknya, klausa ORDER BY
dan GROUP BY
secara implisit meratakan data yang dikueri. Untuk situasi ketika data tidak diratakan secara implisit,
seperti membuat kueri beberapa kolom berulang dalam legacy SQL, Anda dapat membuat kueri data menggunakan
fungsi SQL FLATTEN
dan WITHIN
.
MERATAKAN
Saat Anda membuat kueri data bertingkat, BigQuery akan meratakan data tabel untuk Anda secara otomatis. Misalnya, mari kita lihat skema sampel untuk data orang:
Last modified Schema Total Rows Total Bytes Expiration ----------------- ----------------------------------- ------------ ------------- ------------ 27 Sep 10:01:06 |- kind: string 4 794 |- fullName: string (required) |- age: integer |- gender: string +- phoneNumber: record | |- areaCode: integer | |- number: integer +- children: record (repeated) | |- name: string | |- gender: string | |- age: integer +- citiesLived: record (repeated) | |- place: string | +- yearsLived: integer (repeated)
Perhatikan bahwa ada beberapa kolom berulang dan bertingkat. Jika Anda menjalankan kueri legacy SQL seperti berikut terhadap tabel orang:
SELECT fullName AS name, age, gender, citiesLived.place, citiesLived.yearsLived FROM [dataset.tableId]
BigQuery akan menampilkan data Anda dengan output yang diratakan:
+---------------+-----+--------+-------------------+------------------------+ | name | age | gender | citiesLived_place | citiesLived_yearsLived | +---------------+-----+--------+-------------------+------------------------+ | John Doe | 22 | Male | Seattle | 1995 | | John Doe | 22 | Male | Stockholm | 2005 | | Mike Jones | 35 | Male | Los Angeles | 1989 | | Mike Jones | 35 | Male | Los Angeles | 1993 | | Mike Jones | 35 | Male | Los Angeles | 1998 | | Mike Jones | 35 | Male | Los Angeles | 2002 | | Mike Jones | 35 | Male | Washington DC | 1990 | | Mike Jones | 35 | Male | Washington DC | 1993 | | Mike Jones | 35 | Male | Washington DC | 1998 | | Mike Jones | 35 | Male | Washington DC | 2008 | | Mike Jones | 35 | Male | Portland | 1993 | | Mike Jones | 35 | Male | Portland | 1998 | | Mike Jones | 35 | Male | Portland | 2003 | | Mike Jones | 35 | Male | Portland | 2005 | | Mike Jones | 35 | Male | Austin | 1973 | | Mike Jones | 35 | Male | Austin | 1998 | | Mike Jones | 35 | Male | Austin | 2001 | | Mike Jones | 35 | Male | Austin | 2005 | | Anna Karenina | 45 | Female | Stockholm | 1992 | | Anna Karenina | 45 | Female | Stockholm | 1998 | | Anna Karenina | 45 | Female | Stockholm | 2000 | | Anna Karenina | 45 | Female | Stockholm | 2010 | | Anna Karenina | 45 | Female | Moscow | 1998 | | Anna Karenina | 45 | Female | Moscow | 2001 | | Anna Karenina | 45 | Female | Moscow | 2005 | | Anna Karenina | 45 | Female | Austin | 1995 | | Anna Karenina | 45 | Female | Austin | 1999 | +---------------+-----+--------+-------------------+------------------------+
Dalam contoh ini, citiesLived.place
sekarang menjadi citiesLived_place
dan
citiesLived.yearsLived
sekarang menjadi citiesLived_yearsLived
.
Meskipun BigQuery dapat meratakan kolom bertingkat secara otomatis, Anda mungkin perlu
memanggil FLATTEN
secara eksplisit saat menangani lebih dari satu kolom berulang. Misalnya,
jika Anda mencoba menjalankan kueri legacy SQL seperti berikut:
SELECT fullName, age FROM [dataset.tableId] WHERE (citiesLived.yearsLived > 1995 ) AND (children.age > 3)
BigQuery akan menampilkan error yang mirip dengan:
Cannot query the cross product of repeated fields children.age and citiesLived.yearsLived
Untuk membuat kueri di lebih dari satu kolom berulang, Anda perlu meratakan salah satu kolom:
SELECT fullName, age, gender, citiesLived.place FROM (FLATTEN([dataset.tableId], children)) WHERE (citiesLived.yearsLived > 1995) AND (children.age > 3) GROUP BY fullName, age, gender, citiesLived.place
Yang akan menghasilkan:
+------------+-----+--------+-------------------+ | fullName | age | gender | citiesLived_place | +------------+-----+--------+-------------------+ | John Doe | 22 | Male | Stockholm | | Mike Jones | 35 | Male | Los Angeles | | Mike Jones | 35 | Male | Washington DC | | Mike Jones | 35 | Male | Portland | | Mike Jones | 35 | Male | Austin | +------------+-----+--------+-------------------+
DALAM Klausa
Kata kunci WITHIN
secara khusus berfungsi dengan fungsi agregat untuk digabungkan di seluruh
turunan dan kolom berulang dalam data dan kolom bertingkat. Saat menentukan kata kunci WITHIN
,
Anda harus menentukan cakupan yang ingin digabungkan:
WITHIN RECORD
: Menggabungkan data pada nilai berulang dalam data.WITHIN node_name
: Menggabungkan data dalam nilai berulang dalam node yang ditentukan, dengan node sebagai node induk dari kolom dalam fungsi agregasi.
Misalkan Anda ingin menemukan jumlah anak yang dimiliki setiap orang pada contoh sebelumnya. Untuk melakukannya, Anda dapat menghitung jumlah children.name yang dimiliki setiap data:
SELECT fullName, COUNT(children.name) WITHIN RECORD AS numberOfChildren FROM [dataset.tableId];
Anda mendapatkan hasil berikut:
+---------------+------------------+ | fullName | numberOfChildren | +---------------+------------------+ | John Doe | 2 | | Jane Austen | 2 | | Mike Jones | 3 | | Anna Karenina | 0 | +---------------+------------------+
Untuk membandingkan, coba cantumkan semua nama anak:
SELECT fullName, children.name FROM [dataset.tableId]
+---------------+---------------+ | fullName | children_name | +---------------+---------------+ | John Doe | Jane | | John Doe | John | | Jane Austen | Josh | | Jane Austen | Jim | | Mike Jones | Earl | | Mike Jones | Sam | | Mike Jones | Kit | | Anna Karenina | None | +---------------+---------------+
Ini cocok dengan hasil kueri WITHIN RECORD
kita. John Doe memiliki dua anak
bernama Jane dan John, Jane Austen memiliki dua anak bernama Josh dan Jim, Mike Jones memiliki tiga
anak bernama Earl, Sam, dan Kit, dan Anna Karenina tidak memiliki anak.
Sekarang, misalkan Anda ingin menemukan berapa kali seseorang tinggal di tempat yang berbeda.
Anda dapat menggunakan klausa WITHIN
untuk menggabungkan satu node tertentu:
SELECT fullName, COUNT(citiesLived.place) WITHIN RECORD AS numberOfPlacesLived, citiesLived.place, COUNT(citiesLived.yearsLived) WITHIN citiesLived AS numberOfTimesInEachCity, FROM [dataset.tableId];
+---------------+---------------------+-------------------+-------------------------+ | fullName | numberOfPlacesLived | citiesLived_place | numberOfTimesInEachCity | +---------------+---------------------+-------------------+-------------------------+ | John Doe | 2 | Seattle | 1 | | John Doe | 2 | Stockholm | 1 | | Mike Jones | 4 | Los Angeles | 4 | | Mike Jones | 4 | Washington DC | 4 | | Mike Jones | 4 | Portland | 4 | | Mike Jones | 4 | Austin | 4 | | Anna Karenina | 3 | Stockholm | 4 | | Anna Karenina | 3 | Moscow | 3 | | Anna Karenina | 3 | Austin | 2 | +---------------+---------------------+-------------------+-------------------------+
Kueri ini melakukan hal berikut:
- Melakukan
WITHIN RECORD
padacitiesLived.place
dan menghitung jumlah tempat tinggal setiap orang - Melakukan
WITHIN
padacitiesLived.yearsLived
dan menghitung berapa kali setiap orang tinggal di setiap kota (hanya dihitung dicitiesLived
).
Menggunakan penggabungan terbatas pada kolom bertingkat dan berulang merupakan salah satu fitur BigQuery yang paling canggih, yang sering kali dapat menghilangkan penggabungan yang mahal dalam kueri.