Intro
Letβs get familiar with the data.
import ibis
from ibis import _
print ("Using ibis version: " , ibis.__version__)
ibis.options.interactive = True
con = ibis.sqlite.connect ("noahs.sqlite" )
customers = con.table('customers' )
products = con.table('products' )
orders = con.table('orders' )
orders_items = con.table('orders_items' )
customers.head()
Using ibis version: 4.1.0
ββββββββββββββ³βββββββββββββββββββ³ββββββββββββββββββ³ββββββββββββββββββββββββββ³βββββββββββββ³βββββββββββββββ
β customerid β name β address β citystatezip β birthdate β phone β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int32 β string β string β string β string β string β
ββββββββββββββΌβββββββββββββββββββΌββββββββββββββββββΌββββββββββββββββββββββββββΌβββββββββββββΌβββββββββββββββ€
β 1001 β Jack Quinn β 201 E Park St β Los Angeles, CA 91343 β 1960-05-14 β 805-287-8515 β
β 1002 β David Powell β 224C Tysens Ln β Staten Island, NY 10306 β 1978-04-04 β 516-768-1652 β
β 1003 β Carrie Green β 1608 W 53rd Way β Tampa, FL 33614 β 1969-01-21 β 727-209-0470 β
β 1004 β Steven Miller β 178Β½ E 7th St β Manhattan, NY 10009 β 1953-08-17 β 607-941-9563 β
β 1005 β Christine Powers β 270 W 242nd St β Bronx, NY 10463 β 1983-06-06 β 212-759-9043 β
ββββββββββββββ΄βββββββββββββββββββ΄ββββββββββββββββββ΄ββββββββββββββββββββββββββ΄βββββββββββββ΄βββββββββββββββ
/home/francois/.local/lib/python3.10/site-packages/ibis/backends/base/sql/alchemy/__init__.py:125: SAWarning: Dialect sqlite+pysqlite does *not* support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.
yield con.execute(*args, **kwargs)
βββββββββββ³ββββββββββββββββββββββββββββββββββββββββββ³βββββββββββββββββ
β sku β desc β wholesale_cost β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β string β string β decimal(10, 2) β
βββββββββββΌββββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββ€
β DLI0002 β Smoked Whitefish Sandwich β 9.33 β
β PET0005 β Vegan Cat Food, Turkey & Chicken β 4.35 β
β HOM0018 β Power Radio (red) β 21.81 β
β KIT0034 β Azure Ladle β 2.81 β
β PET0041 β Gluten-free Cat Food, Pumpkin & Pumpkin β 4.60 β
βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββ
/home/francois/.local/lib/python3.10/site-packages/ibis/backends/base/sql/alchemy/__init__.py:125: SAWarning: Dialect sqlite+pysqlite does *not* support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.
yield con.execute(*args, **kwargs)
TypeError: must be real number, not str
TypeError: must be real number, not str
/home/francois/.local/lib/python3.10/site-packages/ibis/backends/base/sql/alchemy/__init__.py:125: SAWarning: Dialect sqlite+pysqlite does *not* support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.
yield con.execute(*args, **kwargs)
βββββββββββ³ββββββββββ³ββββββββ³βββββββββββββββββ
β orderid β sku β qty β unit_price β
β‘βββββββββββββββββββββββββββββββββββββββββββββ©
β int32 β string β int32 β decimal(10, 2) β
βββββββββββΌββββββββββΌββββββββΌβββββββββββββββββ€
β 1001 β COL0820 β 1 β 25.52 β
β 1002 β TOY8907 β 1 β 12.92 β
β 1002 β KIT5813 β 1 β 7.99 β
β 1002 β KIT3981 β 2 β 7.21 β
β 1003 β KIT7098 β 1 β 12.53 β
βββββββββββ΄ββββββββββ΄ββββββββ΄βββββββββββββββββ
There is definitely something weird with the data types provided in the SQLite database, so letβs use pyarrow to create parquet files from the CSV and check that the data types are what is expected.
from pyarrow import csv
import pyarrow.parquet as pq
customers = csv.read_csv("noahs-customers.csv" )
pq.write_table(customers, "noahs-customers.parquet" )
orders = csv.read_csv("noahs-orders.csv" )
pq.write_table(orders, "noahs-orders.parquet" )
products = csv.read_csv("noahs-products.csv" )
pq.write_table(products, "noahs-products.parquet" )
items_orders = csv.read_csv("noahs-orders_items.csv" )
pq.write_table(items_orders, "noahs-orders_items.parquet" )
con = ibis.connect ("duckdb://" )
customers = con.read_parquet('noahs-customers.parquet' )
products = con.read_parquet('noahs-products.parquet' )
orders_items = con.read_parquet('noahs-orders_items.parquet' )
orders = con.read_parquet('noahs-orders.parquet' )
Day 1
We need to convert the last names of the customers and find one that matches their phone number.
(
customers
.mutate(last_name = _.name.re_extract(r"(.+)\s(.+)" , 2 ).lower())
.filter (_.last_name.length() == 10 )
.mutate(converted = _.last_name.re_replace("[abc]" , "2" )
.re_replace("[def]" , "3" )
.re_replace("[ghi]" , "4" )
.re_replace("[jkl]" , "5" )
.re_replace("[mno]" , "6" )
.re_replace("[pqrs]" ,"7" )
.re_replace("[tuv]" , "8" )
.re_replace("[wxyz]" ,"9" )
)
.mutate(edit_phone = _.phone.re_replace("-" , "" ))
.filter (_.edit_phone == _.converted)
.select(_.name, _.phone, _.converted, _.edit_phone)
)
ββββββββββββββββββ³βββββββββββββββ³βββββββββββββ³βββββββββββββ
β name β phone β converted β edit_phone β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β string β string β string β string β
ββββββββββββββββββΌβββββββββββββββΌβββββββββββββΌβββββββββββββ€
β Sam Guttenberg β 488-836-2374 β 4888362374 β 4888362374 β
ββββββββββββββββββ΄βββββββββββββββ΄βββββββββββββ΄βββββββββββββ
Day 2
We are looking for customers who have bought coffee/bagels, in 2017, that have the initals JD.
(
products.filter (_.desc.lower().contains("coffee, drip" ))
)
βββββββββββ³βββββββββββββββ³βββββββββββββββββ
β sku β desc β wholesale_cost β
β‘ββββββββββββββββββββββββββββββββββββββββββ©
β string β string β float64 β
βββββββββββΌβββββββββββββββΌβββββββββββββββββ€
β DLI1464 β Coffee, Drip β 6.21 β
βββββββββββ΄βββββββββββββββ΄βββββββββββββββββ
(
products.filter (_.desc.lower().contains("bagel" ))
)
βββββββββββ³ββββββββββββββββ³βββββββββββββββββ
β sku β desc β wholesale_cost β
β‘βββββββββββββββββββββββββββββββββββββββββββ©
β string β string β float64 β
βββββββββββΌββββββββββββββββΌβββββββββββββββββ€
β BKY4234 β Caraway Bagel β 6.23 β
β BKY5887 β Sesame Bagel β 6.38 β
βββββββββββ΄ββββββββββββββββ΄βββββββββββββββββ
βββββββββββ³ββββββββββ³ββββββββ³βββββββββββββ
β orderid β sku β qty β unit_price β
β‘βββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β int64 β float64 β
βββββββββββΌββββββββββΌββββββββΌβββββββββββββ€
β 1001 β COL0820 β 1 β 25.52 β
β 1002 β TOY8907 β 1 β 12.92 β
β 1002 β KIT5813 β 1 β 7.99 β
β 1002 β KIT3981 β 2 β 7.21 β
β 1003 β KIT7098 β 1 β 12.53 β
βββββββββββ΄ββββββββββ΄ββββββββ΄βββββββββββββ
(
orders_items.filter (_.sku.isin(['DLI1464' , 'BKY4234' , 'BKY5887' ]))
.select(_.orderid)
.distinct()
.left_join(orders, _.orderid == orders.orderid)
.select(_.orderid_x, _.customerid, _.ordered, _.total)
.mutate(year = _.ordered.strftime('%Y' ))
.filter (_.year == '2017' )
.left_join(customers, _.customerid == customers.customerid)
.select(_.orderid_x, _.total, _.customerid_y, _.name, _.phone, _.address, _.citystatezip)
.filter (_.name.re_search('J(.+)\sD(.+)' ))
)
βββββββββββββ³ββββββββββ³βββββββββββββββ³βββββββββββββββ³βββββββββββββββ³βββββββββββββββββββ³ββββββββββββββββββββββββββββ
β orderid_x β total β customerid_y β name β phone β address β citystatezip β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β float64 β int64 β string β string β string β string β
βββββββββββββΌββββββββββΌβββββββββββββββΌβββββββββββββββΌβββββββββββββββΌβββββββββββββββββββΌββββββββββββββββββββββββββββ€
β 7409 β 33.22 β 4164 β Jeremy Davis β 212-771-8924 β 134-10 Foch Blvd β South Ozone Park, NY 114β¦ β
βββββββββββββ΄ββββββββββ΄βββββββββββββββ΄βββββββββββββββ΄βββββββββββββββ΄βββββββββββββββββββ΄ββββββββββββββββββββββββββββ
orders_items.filter (_.orderid == 7409 )
βββββββββββ³ββββββββββ³ββββββββ³βββββββββββββ
β orderid β sku β qty β unit_price β
β‘βββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β int64 β float64 β
βββββββββββΌββββββββββΌββββββββΌβββββββββββββ€
β 7409 β DLI1464 β 1 β 7.73 β
β 7409 β KIT5861 β 1 β 12.53 β
β 7409 β HOM8601 β 1 β 4.48 β
β 7409 β BKY5887 β 1 β 8.48 β
βββββββββββ΄ββββββββββ΄ββββββββ΄βββββββββββββ
Day 3
We are looking for someone born in the year of the dog (comes back every 12 years: 2030, 2018, 2006, 1994, 1982, 1970, 1958), is an Aries (born between March 21 and April 19), and lives in South Ozone Park (see previous answer).
# Aries born in the year of the Dog
# year of the dog comes back every 12 years: 2030, 2018, 2006, 1994, 1982, 1970, 1958
# Aries: March 21 to Apr 19
# range for the birth days
customers.filter ((_.birthdate == _.birthdate.min ()) | (_.birthdate == _.birthdate.max ()))
ββββββββββββββ³ββββββββββββββββ³βββββββββββββββββββ³βββββββββββββββββββββ³βββββββββββββ³βββββββββββββββ
β customerid β name β address β citystatezip β birthdate β phone β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β string β string β date β string β
ββββββββββββββΌββββββββββββββββΌβββββββββββββββββββΌβββββββββββββββββββββΌβββββββββββββΌβββββββββββββββ€
β 2658 β Timothy Evans β 335Β½ 20th St β Brooklyn, NY 11215 β 1935-02-14 β 838-950-3946 β
β 7499 β Barry Barnes β 2758 Mermaid Ave β Brooklyn, NY 11224 β 2000-12-30 β 516-305-8067 β
ββββββββββββββ΄ββββββββββββββββ΄βββββββββββββββββββ΄βββββββββββββββββββββ΄βββββββββββββ΄βββββββββββββββ
dog_years = ["1994" , "1982" , "1970" , "1958" , "1936" ]
(
customers
.mutate(year = _.birthdate.year())
.filter (_.year.isin(dog_years))
.filter (
((_.birthdate.month() == 3 ) & (_.birthdate.day() >= 21 )) |
((_.birthdate.month() == 4 ) & (_.birthdate.day() <= 19 ))
)
.filter (_.citystatezip.ilike("south ozone park%" ))
)
ββββββββββββββ³βββββββββββββββ³ββββββββββββββββββ³βββββββββββββββββββββββββββββ³βββββββββββββ³βββββββββββββββ³ββββββββ
β customerid β name β address β citystatezip β birthdate β phone β year β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β string β string β date β string β int32 β
ββββββββββββββΌβββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββββββββββΌβββββββββββββΌβββββββββββββββΌββββββββ€
β 2274 β Brent Nguyen β 109-19 110th St β South Ozone Park, NY 11420 β 1958-03-25 β 516-636-7397 β 1958 β
ββββββββββββββ΄βββββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββββββββββββββββ΄βββββββββββββ΄βββββββββββββββ΄ββββββββ
Day 4
We are looking for someone who buys regularly baked good between 4 and 5am.
(
products.filter (_.sku.startswith("BKY" ))
.left_join(orders_items, orders_items.sku == _.sku)
.select(_.orderid)
.left_join(orders, orders.orderid == _.orderid)
.filter ((_.ordered.hour() >= 4 ) & (_.ordered.hour() < 5 ))
.group_by(_.customerid)
.aggregate(n_visits = _.count())
.filter (_.n_visits == _.n_visits.max ())
.join(customers, customers.customerid == _.customerid)
)
ββββββββββββββ³βββββββββββ³βββββββββββββββββββ³βββββββββββββββββββ³ββββββββββββββββββ³βββββββββββββ³βββββββββββββββ
β customerid β n_visits β name β address β citystatezip β birthdate β phone β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β int64 β string β string β string β date β string β
ββββββββββββββΌβββββββββββΌβββββββββββββββββββΌβββββββββββββββββββΌββββββββββββββββββΌβββββββββββββΌβββββββββββββββ€
β 5375 β 10 β Christina Booker β 1127 Grinnell Pl β Bronx, NY 10474 β 1981-01-08 β 718-649-9036 β
ββββββββββββββ΄βββββββββββ΄βββββββββββββββββββ΄βββββββββββββββββββ΄ββββββββββββββββββ΄βββββββββββββ΄βββββββββββββββ
Day 5
We are looking for someone who buys a lot of cat food for their old cats and lives in Queens Village.
(
products.filter (_.desc.lower().contains("senior cat" ))
)
βββββββββββ³ββββββββββββββββββββββββββββββββββββββββββββββββ³βββββββββββββββββ
β sku β desc β wholesale_cost β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β string β string β float64 β
βββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββββ€
β PET0096 β Wet Senior Cat Food, Turkey & Shrimp β 3.11 β
β PET0304 β Gluten-free Senior Cat Food, Chicken & Turkey β 4.24 β
β PET0925 β Senior Cat Food β 3.84 β
β PET0977 β Vegan Senior Cat Food, Chicken & Beef β 4.36 β
β PET1090 β Vegan Senior Cat Food, Tuna & Duck β 4.39 β
β PET1220 β Dry Senior Cat Food, Salmon & Shrimp β 3.51 β
β PET1536 β Dry Senior Cat Food, Chicken & Chicken β 2.26 β
β PET1849 β Vegan Senior Cat Food, Duck & Pumpkin β 4.65 β
β PET1909 β Vegan Senior Cat Food, Chicken & Salmon β 4.60 β
β PET1919 β Gluten-free Senior Cat Food, Shrimp & Tuna β 4.23 β
β β¦ β β¦ β β¦ β
βββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββ
## let's find out who buys senior cat food
(
products.filter (_.desc.lower().contains("senior cat" ))
.left_join(orders_items, orders_items.sku == _.sku)
.select(_.orderid)
.left_join(orders, orders.orderid == _.orderid)
.select(_.customerid)
.distinct()
.left_join(customers, customers.customerid == _.customerid)
.filter (_.citystatezip.contains("Queens Village" ))
)
ββββββββββββββββ³βββββββββββββββ³βββββββββββββ³ββββββββββββββββββ³βββββββββββββββββββββββββ³βββββββββββββ³βββββββββββββββ
β customerid_x β customerid_y β name β address β citystatezip β birthdate β phone β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β int64 β string β string β string β date β string β
ββββββββββββββββΌβββββββββββββββΌβββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββββββΌβββββββββββββΌβββββββββββββββ€
β 5486 β 5486 β Sam House β 220-8 111th Ave β Queens Village, NY 11β¦ β 1955-11-10 β 607-836-2966 β
β 7675 β 7675 β Anita Koch β 106-51 214th St β Queens Village, NY 11β¦ β 1955-11-14 β 315-492-7411 β
ββββββββββββββββ΄βββββββββββββββ΄βββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββββββββββββ΄βββββββββββββ΄βββββββββββββββ
## it's not quite enough, let's compare how much they buy
(
products.filter (_.desc.lower().contains("senior cat" ))
.left_join(orders_items, orders_items.sku == _.sku)
.select(_.orderid)
.left_join(orders, orders.orderid == _.orderid)
.group_by(_.customerid)
.aggregate(_.total.sum ().name("total_catfood" ))
.left_join(customers, customers.customerid == _.customerid)
.filter (_.citystatezip.contains("Queens Village" ))
.select(_.customerid_x, _.name, _.total_catfood, _.phone)
)
ββββββββββββββββ³βββββββββββββ³ββββββββββββββββ³βββββββββββββββ
β customerid_x β name β total_catfood β phone β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β float64 β string β
ββββββββββββββββΌβββββββββββββΌββββββββββββββββΌβββββββββββββββ€
β 5486 β Sam House β 231.88 β 607-836-2966 β
β 7675 β Anita Koch β 699.98 β 315-492-7411 β
ββββββββββββββββ΄βββββββββββββ΄ββββββββββββββββ΄βββββββββββββββ
Day 6
We are looking for someone who minimizes the profit on their purchases at Noahβs Market.
(
orders_items
.left_join(products, products.sku == _.sku)
.mutate(profit = _.unit_price - _.wholesale_cost)
.group_by(_.orderid)
.aggregate(_.profit.sum ().name("total_profit_per_order" ))
.left_join(orders, orders.orderid == _.orderid)
.group_by(_.customerid)
.aggregate(_.total_profit_per_order.sum ().name("total_profit_per_customer" ))
.filter (_.total_profit_per_customer == _.total_profit_per_customer.min ())
.join(customers, customers.customerid == _.customerid)
.select(_.customerid, _.name, _.phone, _.total_profit_per_customer)
)
ββββββββββββββ³βββββββββββββββββ³βββββββββββββββ³ββββββββββββββββββββββββββββ
β customerid β name β phone β total_profit_per_customer β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β string β float64 β
ββββββββββββββΌβββββββββββββββββΌβββββββββββββββΌββββββββββββββββββββββββββββ€
β 8342 β Emily Randolph β 914-868-0316 β -313.16 β
ββββββββββββββ΄βββββββββββββββββ΄βββββββββββββββ΄ββββββββββββββββββββββββββββ
Day 7
We are looking for people who are buying the same product but in different colors (colors are indicated in parentheses in the descriptions), and that have made purchases one after the other (they were following each other in line).
(
products
.filter (_.desc.re_search('.+\s\(.+\)$' )) ## colors are noted in parenthesis
.left_join(orders_items, orders_items.sku == _.sku)
.select(_.orderid, _.desc)
.left_join(orders, orders.orderid == _.orderid)
.order_by(_.ordered)
.mutate(
lag_customerid = _.customerid.lag(),
lag_ordered = _.ordered.lag()
)
.filter (_.lag_customerid == 8342 )
.select(_.orderid_x, _.desc, _.customerid, _.ordered, _.lag_customerid, _.lag_ordered)
)
βββββββββββββ³ββββββββββββββββββββββββββββ³βββββββββββββ³ββββββββββββββββββββββ³βββββββββββββββββ³ββββββββββββββββββββββ
β orderid_x β desc β customerid β ordered β lag_customerid β lag_ordered β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β int64 β timestamp β int64 β timestamp β
βββββββββββββΌββββββββββββββββββββββββββββΌβββββββββββββΌββββββββββββββββββββββΌβββββββββββββββββΌββββββββββββββββββββββ€
β 12625 β Automatic Mixer (white) β 1865 β 2017-05-28 09:15:47 β 8342 β 2017-05-28 09:15:06 β
β 86372 β Electric Machine (purple) β 8835 β 2019-06-01 12:50:25 β 8342 β 2019-06-01 12:50:16 β
β 94040 β Electric Toaster (blue) β 8342 β 2019-08-18 14:20:28 β 8342 β 2019-08-18 14:20:28 β
β 94044 β Noah's Gift Box (green) β 10880 β 2019-08-18 14:57:19 β 8342 β 2019-08-18 14:20:28 β
β 96223 β Super Widget (white) β 11942 β 2019-09-09 16:53:22 β 8342 β 2019-09-09 16:30:05 β
β 154876 β Electric Crockpot (purplβ¦ β 8342 β 2021-04-17 19:52:28 β 8342 β 2021-04-17 19:52:28 β
β 154879 β Jigsaw Puzzle (Moses andβ¦ β 2476 β 2021-04-17 20:22:32 β 8342 β 2021-04-17 19:52:28 β
β 200952 β Noah's Jersey (puce) β 7880 β 2022-07-26 09:48:32 β 8342 β 2022-07-26 08:18:05 β
βββββββββββββ΄ββββββββββββββββββββββββββββ΄βββββββββββββ΄ββββββββββββββββββββββ΄βββββββββββββββββ΄ββββββββββββββββββββββ
# I need to figure out how to do the time difference because here I'm doing it by eye
# and ideally we need to compare the content of their orders and remove lines from the same order
# It's probably not in 2017 because that was the beginning of the story
customers.filter (_.customerid == 8835 )
ββββββββββββββ³βββββββββββββββββ³ββββββββββββββββ³ββββββββββββββββββββββββββ³βββββββββββββ³βββββββββββββββ
β customerid β name β address β citystatezip β birthdate β phone β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β int64 β string β string β string β date β string β
ββββββββββββββΌβββββββββββββββββΌββββββββββββββββΌββββββββββββββββββββββββββΌβββββββββββββΌβββββββββββββββ€
β 8835 β Jonathan Adams β 644 Targee St β Staten Island, NY 10304 β 1975-08-26 β 315-618-5263 β
ββββββββββββββ΄βββββββββββββββββ΄ββββββββββββββββ΄ββββββββββββββββββββββββββ΄βββββββββββββ΄βββββββββββββββ
Day 8
We are looking for someone who has purchased lots of collectible (prefix with COL
in the products table).
(
products.filter (_.sku.lower().contains("col" ))
.left_join(orders_items, orders_items.sku == _.sku)
.select(_.orderid, _.sku_x)
.left_join(orders, orders.orderid == _.orderid)
.group_by(_.customerid)
.aggregate(n_collect = _.count())
.order_by(ibis.desc(_.n_collect))
.left_join(customers, customers.customerid == _.customerid)
.select(_.name, _.phone, _.n_collect)
)
βββββββββββββββββββββ³βββββββββββββββ³ββββββββββββ
β name β phone β n_collect β
β‘βββββββββββββββββββββββββββββββββββββββββββββββ©
β string β string β int64 β
βββββββββββββββββββββΌβββββββββββββββΌββββββββββββ€
β Travis Bartlett β 929-906-5980 β 111 β
β Justin Jimenez β 516-722-4758 β 31 β
β Joshua Smith β 914-243-3254 β 30 β
β Tyler Hickman β 585-307-8945 β 27 β
β Rachel Richardson β 212-778-9867 β 26 β
β Kim Yang β 516-399-6228 β 26 β
β Joshua Parks β 680-594-9693 β 26 β
β Amber Porter β 838-307-4383 β 26 β
β Chelsea Marsh β 315-565-2714 β 26 β
β Jennifer Daniels β 516-994-3023 β 26 β
β β¦ β β¦ β β¦ β
βββββββββββββββββββββ΄βββββββββββββββ΄ββββββββββββ