What do you do when you want to query over multiple parquet files but the schemas don’t quite line up? Let’s find out šš»
I’ve got a set of parquet files in S3 (well, lakeFS1, but let’s not quibble over details) with the same datail split by year:
$ lakectl fs ls lakefs://drones03/main/drone-registrations/
object 2023-03-01 09:47:36 +0000 UTC 30.7 kB Registations-P107-Active-2016.parquet
object 2023-03-01 09:48:54 +0000 UTC 119.7 kB Registations-P107-Active-2017.parquet
object 2023-03-01 09:44:47 +0000 UTC 594.3 kB Registations-P107-Active-2018.parquet
object 2023-03-01 09:45:04 +0000 UTC 1.3 MB Registations-P107-Active-2019.parquet
object 2023-03-01 09:48:12 +0000 UTC 2.8 MB Registations-P107-Active-2020.parquet
object 2023-03-01 09:48:51 +0000 UTC 3.2 MB Registations-P107-Active-2021.parquet
I want to query and manipulate the data. DuckDB is my friend since it works with parquet files. I fire it up with an empty database:
$ duckdb drones.duckdb
A DESCRIBE gives me the schema:
D DESCRIBE SELECT * FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-*.parquet') ;
āāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāā¬āāāāāāāāāā¬āāāāāāāāāā¬āāāāāāāāāā¬āāāāāāāāāā
ā column_name ā column_type ā null ā key ā default ā extra ā
ā varchar ā varchar ā varchar ā varchar ā varchar ā varchar ā
āāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāā¼āāāāāāāāāā¼āāāāāāāāāā¼āāāāāāāāāā¼āāāāāāāāāā¤
ā Registration Date ā VARCHAR ā YES ā ā ā ā
ā Registion Expire Dt ā VARCHAR ā YES ā ā ā ā
ā Asset Type ā VARCHAR ā YES ā ā ā ā
ā RID Equipped ā BOOLEAN ā YES ā ā ā ā
ā Asset Model ā VARCHAR ā YES ā ā ā ā
ā Physical City ā VARCHAR ā YES ā ā ā ā
ā Physical State/Province ā VARCHAR ā YES ā ā ā ā
ā Physical Postal Code ā BIGINT ā YES ā ā ā ā
ā Mailing City ā VARCHAR ā YES ā ā ā ā
ā Mailing State/Province ā VARCHAR ā YES ā ā ā ā
ā Mailing Postal Code ā BIGINT ā YES ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāā“āāāāāāāāāā“āāāāāāāāāā“āāāāāāāāāā“āāāāāāāāāā¤
ā 11 rows 6 columns ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Now I should be able to query a sample of the data to check it out, right. Right?
D SELECT *
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-*.parquet')
USING SAMPLE 5 ROWS;
100% āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Error: Conversion Error: Could not convert string 'V1M 2K9' to INT64
Spoiler: UNION_BY_NAME š
After posting this blog, two people both suggested using the UNION_BY_NAME option which was added to DuckDB recently. This worked perfectly:
D SELECT *
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-*.parquet',
union_by_name=True)
USING SAMPLE 5 ROWS;
100% āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāā¬āāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāā
ā Registration Date ā Registion Expire Dt ā Asset Type ā RID Equipped ā ⦠ā Physical Postal Code ā Mailing City ā Mailing State/Prov⦠ā Mailing Postal Code ā
ā varchar ā varchar ā varchar ā boolean ā ā varchar ā varchar ā varchar ā varchar ā
āāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāā¼āāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāā¤
ā 2021-09-27 17:17:1⦠ā 2024-09-27 ā HOMEBUILT_UAS ā false ā ⦠ā 32177 ā Palatka ā FL ā 32177 ā
ā 2020-12-06 02:18:5⦠ā 2023-12-05 ā PURCHASED ā ā ⦠ā 10065 ā New York ā NY ā 10065 ā
ā 2019-10-08 15:33:3⦠ā 2022-10-08 ā PURCHASED ā ā ⦠ā 83706 ā Boise ā ID ā 83706 ā
ā 2020-12-03 14:26:0⦠ā 2023-12-03 ā PURCHASED ā ā ⦠ā 49506 ā Grand Rapids ā MI ā 49506 ā
ā 2020-01-27 18:57:0⦠ā 2023-01-27 ā HOME_BUILT ā ā ⦠ā 35758 ā Madison ā AL ā 35758 ā
āāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāā“āāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāā¤
ā 5 rows 11 columns (8 shown) ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Thanks @mraasveldt and @__AlexMonahan__šš»
Problem solved. But if you want to follow along with another option, read onā¦
Back to the Detective Story š
So, we have this problem:
D SELECT *
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-*.parquet')
USING SAMPLE 5 ROWS;
100% āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Error: Conversion Error: Could not convert string 'V1M 2K9' to INT64
Huh. That sucks. Let’s try it on a single file:
D SELECT * FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet') USING SAMPLE 5 ROWS;
āāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāā¬āāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāā
ā Registration Date ā Registion Expire Dt ā Asset Type ā RID Equipped ā ⦠ā Physical Postal Code ā Mailing City ā Mailing State/Prov⦠ā Mailing Postal Code ā
ā varchar ā varchar ā varchar ā boolean ā ā int64 ā varchar ā varchar ā int64 ā
āāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāā¼āāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāā¤
ā 2016-09-28 19:27:5⦠ā 2025-09-28 ā TRADITIONAL_UAS ā false ā ⦠ā 80203 ā Denver ā CO ā 80203 ā
ā 2016-10-26 13:10:2⦠ā 2022-10-26 ā PURCHASED ā ā ⦠ā 33611 ā Tampa ā FL ā 33611 ā
ā 2016-10-25 15:58:4⦠ā 2022-10-25 ā PURCHASED ā ā ⦠ā 23337 ā Wallops Island ā VA ā 23337 ā
ā 2016-11-30 17:17:1⦠ā 2022-11-30 ā PURCHASED ā ā ⦠ā 32114 ā Daytona Beach ā FL ā 32114 ā
ā 2016-10-25 15:58:4⦠ā 2022-10-25 ā PURCHASED ā ā ⦠ā 23337 ā Wallops Island ā VA ā 23337 ā
āāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāā“āāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāā¤
ā 5 rows 11 columns (8 shown) ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
D
That works, so we’re going to have to narrow down the problem. As a side note, I should probably log an enhancement request for more detailed error messages (for example, which file had the error, and which field).
Looking at the error message there’s a data type problem with an INT64 field (BIGINT). In the schema there are two fields with that:
Physical Postal Code
Mailing Postal Code
DuckDB’s parquet docs page points me to the parquet_schema function, so let’s have a look at these fields over the files in question:
SELECT file_name, name, type, logical_type
FROM parquet_schema('s3://drones03/main/drone-registrations/Registations-P107-Active-*.parquet')
WHERE name like '%Postal Code%';
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāā¬āāāāāāāāāāāāāāā
ā file_name ā name ā type ā logical_type ā
ā varchar ā varchar ā varchar ā varchar ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¤
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā Physical Postal Code ā INT64 ā ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā Mailing Postal Code ā INT64 ā ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā Physical Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā Mailing Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2018.parquet ā Physical Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2018.parquet ā Mailing Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2019.parquet ā Physical Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2019.parquet ā Mailing Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2020.parquet ā Physical Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2020.parquet ā Mailing Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā Physical Postal Code ā BYTE_ARRAY ā StringType() ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā Mailing Postal Code ā BYTE_ARRAY ā StringType() ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāā“āāāāāāāāāāāāāāā¤
ā 12 rows 4 columns ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
So there’s the problem; the 2016 file uses INT64 for those fields whilst the remaining files use a string. The SELECT that I ran above against all the files failed because when it tried to apply the schema of the first file against the data read from the others it ended up trying to convert a string to a number, which is never going to end well.
Here’s one way to fix things with a UNION ALL. Note the use of filename metadata column to help verify the data we’re getting is what’s expected. To start with let’s just try it against two files:
SELECT filename, CAST("Physical Postal Code" AS VARCHAR) AS "Physical Postal Code"
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet', filename=true)
USING SAMPLE 5 ROWS
UNION ALL
SELECT filename, "Physical Postal Code"
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet', filename=true)
USING SAMPLE 5 ROWS;
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā
ā filename ā Physical Postal Code ā
ā varchar ā varchar ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā¤
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 80237 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 35222 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 36112 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 87123 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 35806 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā 68179 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā 32114 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā 93637 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā 33611 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā 36112 ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāā¤
ā 10 rows 2 columns ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Now we just need to specify the remainder of the files. Previously we wildcarded, but we can’t include the 2016 file in that (since we’re handling that with a CAST in the first block of the UNION), so we need to modify it. We’ll test our new selection pattern first:
SELECT filename
FROM read_parquet(['s3://drones03/main/drone-registrations/Registations-P107-Active-201[7-9].parquet',
's3://drones03/main/drone-registrations/Registations-P107-Active-202*.parquet'],
filename=true)
GROUP BY filename;
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā filename ā
ā varchar ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2018.parquet ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2019.parquet ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2020.parquet ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Let’s test this with the UNION:
SELECT filename, CAST("Physical Postal Code" AS VARCHAR) AS "Physical Postal Code"
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet', filename=true)
USING SAMPLE 5 ROWS
UNION ALL
SELECT filename, "Physical Postal Code"
FROM read_parquet(['s3://drones03/main/drone-registrations/Registations-P107-Active-201[7-9].parquet',
's3://drones03/main/drone-registrations/Registations-P107-Active-202*.parquet'], filename=true)
USING SAMPLE 5 ROWS;
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā
ā filename ā Physical Postal Code ā
ā varchar ā varchar ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā¤
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 87123 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 32114 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 67301 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 35806 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 32114 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā 35806 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā 98290 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā 07641 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā 33133 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā 20166 ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāā¤
ā 10 rows 2 columns ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Now we can put this all together to do what we were trying to do in the first place; look at a sample of rows from across the set of files - but making allowances for the mismatched datatypes of the schema.
WITH x AS (SELECT "Registration Date",
"Registion Expire Dt",
"Asset Type",
"RID Equipped",
"Asset Model",
"Physical City",
"Physical State/Province",
CAST("Physical Postal Code" AS VARCHAR) AS "Physical Postal Code",
"Mailing City",
"Mailing State/Province",
CAST("Mailing Postal Code" AS VARCHAR) AS "Mailing Postal Code",
filename
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet', filename=true)
UNION ALL
SELECT *
FROM read_parquet (['s3://drones03/main/drone-registrations/Registations-P107-Active-201[7-9].parquet',
's3://drones03/main/drone-registrations/Registations-P107-Active-202*.parquet'],
filename=true)
)
SELECT * FROM x
USING SAMPLE 10 ROWS;
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Registration Date ā Registion Expire Dt ā Asset Type ā RID Equipped ā Asset Model ā Physical City ā Physical State/Province ā Physical Postal Code ā Mailing City ā Mailing State/Province ā Mailing Postal Code ā filename ā
ā varchar ā varchar ā varchar ā boolean ā varchar ā varchar ā varchar ā varchar ā varchar ā varchar ā varchar ā varchar ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā 2021-03-24 13:35:06.817000 ā 2024-03-24 ā TRADITIONAL_UAS ā false ā Phantom 4 Pro V2 ā Minneapolis ā MN ā 55423 ā Minneapolis ā MN ā 55423 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā
ā 2021-12-06 12:43:38.265000 ā 2024-12-06 ā TRADITIONAL_UAS ā false ā Air 2S ā Wo;;ots ā CA ā 95490 ā Wo;;ots ā CA ā 95490 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā
ā 2021-12-11 01:49:20.235000 ā 2024-12-10 ā TRADITIONAL_UAS ā false ā Mavic Air ā Rocklin ā CA ā 95677 ā Rocklin ā CA ā 95677 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā
ā 2020-06-01 12:43:09.114000 ā 2023-06-01 ā PURCHASED ā ā Mavic 2 Air ā Loveland ā CO ā 80538 ā Loveland ā CO ā 80538 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2020.parquet ā
ā 2021-10-19 22:03:03.630000 ā 2024-10-19 ā HOMEBUILT_UAS ā false ā X1 ā Philadelphia ā PA ā 19146 ā Philadelphia ā PA ā 19146 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā
ā 2020-12-31 00:59:16.326000 ā 2023-12-30 ā PURCHASED ā ā SP7100 ā Cornelius ā OR ā 97113 ā Cornelius ā OR ā 97113 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2020.parquet ā
ā 2020-10-14 18:31:39.662000 ā 2023-10-14 ā PURCHASED ā ā Phantom Rtk 4 ā San Antonio ā TX ā 78216 ā San Antonio ā TX ā 78216 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2020.parquet ā
ā 2019-05-14 23:10:35.507000 ā 2025-05-14 ā TRADITIONAL_UAS ā false ā Mavic Pro 2 ā Greensboro ā NC ā 27409 ā Greensboro ā NC ā 27409 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2019.parquet ā
ā 2019-05-29 14:50:18.922000 ā 2025-05-29 ā TRADITIONAL_UAS ā false ā Phantom 4 Pro ā Brighton ā CO ā 80601 ā Brighton ā CO ā 80601 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2019.parquet ā
ā 2021-02-06 14:56:38.651000 ā 2024-02-06 ā PURCHASED ā ā Mavic 2 Pro ā Louisville ā KY ā 40204 ā Louisville ā KY ā 40204 ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā 10 rows 12 columns ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
This looks good, but we should check we’re getting data from all files. We’ll do that with a COUNT aggregate against the CTE:
WITH x AS (SELECT "Registration Date",
"Registion Expire Dt",
"Asset Type",
"RID Equipped",
"Asset Model",
"Physical City",
"Physical State/Province",
CAST("Physical Postal Code" AS VARCHAR) AS "Physical Postal Code",
"Mailing City",
"Mailing State/Province",
CAST("Mailing Postal Code" AS VARCHAR) AS "Mailing Postal Code",
filename
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet', filename=true)
UNION ALL
SELECT *
FROM read_parquet (['s3://drones03/main/drone-registrations/Registations-P107-Active-201[7-9].parquet',
's3://drones03/main/drone-registrations/Registations-P107-Active-202*.parquet'],
filename=true)
)
SELECT filename, COUNT(*)
FROM x
GROUP BY filename
ORDER BY filename;āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāā
ā filename ā count_star() ā
ā varchar ā int64 ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāā¤
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet ā 1280 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2017.parquet ā 5819 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2018.parquet ā 24695 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2019.parquet ā 60105 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2020.parquet ā 143670 ā
ā s3://drones03/main/drone-registrations/Registations-P107-Active-2021.parquet ā 162826 ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāā
Looks good to me!
For a finishing touch we could even wrap it in a VIEW:
CREATE OR REPLACE VIEW Registations_P107_Active AS
WITH x AS (SELECT "Registration Date",
"Registion Expire Dt",
"Asset Type",
"RID Equipped",
"Asset Model",
"Physical City",
"Physical State/Province",
CAST("Physical Postal Code" AS VARCHAR) AS "Physical Postal Code",
"Mailing City",
"Mailing State/Province",
CAST("Mailing Postal Code" AS VARCHAR) AS "Mailing Postal Code",
filename
FROM read_parquet('s3://drones03/main/drone-registrations/Registations-P107-Active-2016.parquet', filename=true)
UNION ALL
SELECT *
FROM read_parquet (['s3://drones03/main/drone-registrations/Registations-P107-Active-201[7-9].parquet',
's3://drones03/main/drone-registrations/Registations-P107-Active-202*.parquet'],
filename=true)
)
SELECT * FROM x;Which then can be used the same as above like this:
SELECT filename, COUNT(*)
FROM Registations_P107_Active
GROUP BY filename;