{
"cells": [
{
"cell_type": "markdown",
"id": "e74edf74",
"metadata": {},
"source": [
"# Window Functions in Action: SQL Analytics for Northwind Traders"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "7a798832",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The sql extension is already loaded. To reload it, use:\n",
" %reload_ext sql\n"
]
}
],
"source": [
"%load_ext sql\n",
"\n",
"connection_string = f'postgresql://postgres:{password}@localhost:5432/northwind'\n",
"\n",
"%sql $connection_string"
]
},
{
"cell_type": "markdown",
"id": "168208d2",
"metadata": {},
"source": [
"#### Exploring the Northwind Database - Getting to Know the Data"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "20cb9a01",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"14 rows affected.\n"
]
},
{
"data": {
"text/html": [
"
\n",
" \n",
" \n",
" name | \n",
" type | \n",
"
\n",
" \n",
" \n",
" \n",
" territories | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" order_details | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" employee_territories | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" us_states | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" customers | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" orders | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" employees | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" shippers | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" products | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" categories | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" suppliers | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" region | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" customer_demographics | \n",
" BASE TABLE | \n",
"
\n",
" \n",
" customer_customer_demo | \n",
" BASE TABLE | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[('territories', 'BASE TABLE'),\n",
" ('order_details', 'BASE TABLE'),\n",
" ('employee_territories', 'BASE TABLE'),\n",
" ('us_states', 'BASE TABLE'),\n",
" ('customers', 'BASE TABLE'),\n",
" ('orders', 'BASE TABLE'),\n",
" ('employees', 'BASE TABLE'),\n",
" ('shippers', 'BASE TABLE'),\n",
" ('products', 'BASE TABLE'),\n",
" ('categories', 'BASE TABLE'),\n",
" ('suppliers', 'BASE TABLE'),\n",
" ('region', 'BASE TABLE'),\n",
" ('customer_demographics', 'BASE TABLE'),\n",
" ('customer_customer_demo', 'BASE TABLE')]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT\n",
" table_name as name,\n",
" table_type as type\n",
"FROM information_schema.tables\n",
"WHERE table_schema = 'public' AND table_type IN ('BASE TABLE', 'VIEW');\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "11a35d51",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"5 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" customer_id | \n",
" company_name | \n",
" contact_name | \n",
" contact_title | \n",
" address | \n",
" city | \n",
" region | \n",
" postal_code | \n",
" country | \n",
" phone | \n",
" fax | \n",
"
\n",
" \n",
" \n",
" \n",
" ALFKI | \n",
" Alfreds Futterkiste | \n",
" Maria Anders | \n",
" Sales Representative | \n",
" Obere Str. 57 | \n",
" Berlin | \n",
" None | \n",
" 12209 | \n",
" Germany | \n",
" 030-0074321 | \n",
" 030-0076545 | \n",
"
\n",
" \n",
" ANATR | \n",
" Ana Trujillo Emparedados y helados | \n",
" Ana Trujillo | \n",
" Owner | \n",
" Avda. de la Constitución 2222 | \n",
" México D.F. | \n",
" None | \n",
" 05021 | \n",
" Mexico | \n",
" (5) 555-4729 | \n",
" (5) 555-3745 | \n",
"
\n",
" \n",
" ANTON | \n",
" Antonio Moreno Taquería | \n",
" Antonio Moreno | \n",
" Owner | \n",
" Mataderos 2312 | \n",
" México D.F. | \n",
" None | \n",
" 05023 | \n",
" Mexico | \n",
" (5) 555-3932 | \n",
" None | \n",
"
\n",
" \n",
" AROUT | \n",
" Around the Horn | \n",
" Thomas Hardy | \n",
" Sales Representative | \n",
" 120 Hanover Sq. | \n",
" London | \n",
" None | \n",
" WA1 1DP | \n",
" UK | \n",
" (171) 555-7788 | \n",
" (171) 555-6750 | \n",
"
\n",
" \n",
" BERGS | \n",
" Berglunds snabbköp | \n",
" Christina Berglund | \n",
" Order Administrator | \n",
" Berguvsvägen 8 | \n",
" Luleå | \n",
" None | \n",
" S-958 22 | \n",
" Sweden | \n",
" 0921-12 34 65 | \n",
" 0921-12 34 67 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[('ALFKI', 'Alfreds Futterkiste', 'Maria Anders', 'Sales Representative', 'Obere Str. 57', 'Berlin', None, '12209', 'Germany', '030-0074321', '030-0076545'),\n",
" ('ANATR', 'Ana Trujillo Emparedados y helados', 'Ana Trujillo', 'Owner', 'Avda. de la Constitución 2222', 'México D.F.', None, '05021', 'Mexico', '(5) 555-4729', '(5) 555-3745'),\n",
" ('ANTON', 'Antonio Moreno Taquería', 'Antonio Moreno', 'Owner', 'Mataderos 2312', 'México D.F.', None, '05023', 'Mexico', '(5) 555-3932', None),\n",
" ('AROUT', 'Around the Horn', 'Thomas Hardy', 'Sales Representative', '120 Hanover Sq.', 'London', None, 'WA1 1DP', 'UK', '(171) 555-7788', '(171) 555-6750'),\n",
" ('BERGS', 'Berglunds snabbköp', 'Christina Berglund', 'Order Administrator', 'Berguvsvägen 8', 'Luleå', None, 'S-958 22', 'Sweden', '0921-12 34 65', '0921-12 34 67')]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT *\n",
"FROM customers\n",
"LIMIT 5;"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "f1d842bf",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"5 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" order_id | \n",
" customer_id | \n",
" employee_id | \n",
" order_date | \n",
" required_date | \n",
" shipped_date | \n",
" ship_via | \n",
" freight | \n",
" ship_name | \n",
" ship_address | \n",
" ship_city | \n",
" ship_region | \n",
" ship_postal_code | \n",
" ship_country | \n",
"
\n",
" \n",
" \n",
" \n",
" 10248 | \n",
" VINET | \n",
" 5 | \n",
" 1996-07-04 | \n",
" 1996-08-01 | \n",
" 1996-07-16 | \n",
" 3 | \n",
" 32.38 | \n",
" Vins et alcools Chevalier | \n",
" 59 rue de l'Abbaye | \n",
" Reims | \n",
" None | \n",
" 51100 | \n",
" France | \n",
"
\n",
" \n",
" 10249 | \n",
" TOMSP | \n",
" 6 | \n",
" 1996-07-05 | \n",
" 1996-08-16 | \n",
" 1996-07-10 | \n",
" 1 | \n",
" 11.61 | \n",
" Toms Spezialitäten | \n",
" Luisenstr. 48 | \n",
" Münster | \n",
" None | \n",
" 44087 | \n",
" Germany | \n",
"
\n",
" \n",
" 10250 | \n",
" HANAR | \n",
" 4 | \n",
" 1996-07-08 | \n",
" 1996-08-05 | \n",
" 1996-07-12 | \n",
" 2 | \n",
" 65.83 | \n",
" Hanari Carnes | \n",
" Rua do Paço, 67 | \n",
" Rio de Janeiro | \n",
" RJ | \n",
" 05454-876 | \n",
" Brazil | \n",
"
\n",
" \n",
" 10251 | \n",
" VICTE | \n",
" 3 | \n",
" 1996-07-08 | \n",
" 1996-08-05 | \n",
" 1996-07-15 | \n",
" 1 | \n",
" 41.34 | \n",
" Victuailles en stock | \n",
" 2, rue du Commerce | \n",
" Lyon | \n",
" None | \n",
" 69004 | \n",
" France | \n",
"
\n",
" \n",
" 10252 | \n",
" SUPRD | \n",
" 4 | \n",
" 1996-07-09 | \n",
" 1996-08-06 | \n",
" 1996-07-11 | \n",
" 2 | \n",
" 51.3 | \n",
" Suprêmes délices | \n",
" Boulevard Tirou, 255 | \n",
" Charleroi | \n",
" None | \n",
" B-6000 | \n",
" Belgium | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(10248, 'VINET', 5, datetime.date(1996, 7, 4), datetime.date(1996, 8, 1), datetime.date(1996, 7, 16), 3, 32.38, 'Vins et alcools Chevalier', \"59 rue de l'Abbaye\", 'Reims', None, '51100', 'France'),\n",
" (10249, 'TOMSP', 6, datetime.date(1996, 7, 5), datetime.date(1996, 8, 16), datetime.date(1996, 7, 10), 1, 11.61, 'Toms Spezialitäten', 'Luisenstr. 48', 'Münster', None, '44087', 'Germany'),\n",
" (10250, 'HANAR', 4, datetime.date(1996, 7, 8), datetime.date(1996, 8, 5), datetime.date(1996, 7, 12), 2, 65.83, 'Hanari Carnes', 'Rua do Paço, 67', 'Rio de Janeiro', 'RJ', '05454-876', 'Brazil'),\n",
" (10251, 'VICTE', 3, datetime.date(1996, 7, 8), datetime.date(1996, 8, 5), datetime.date(1996, 7, 15), 1, 41.34, 'Victuailles en stock', '2, rue du Commerce', 'Lyon', None, '69004', 'France'),\n",
" (10252, 'SUPRD', 4, datetime.date(1996, 7, 9), datetime.date(1996, 8, 6), datetime.date(1996, 7, 11), 2, 51.3, 'Suprêmes délices', 'Boulevard Tirou, 255', 'Charleroi', None, 'B-6000', 'Belgium')]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT *\n",
"FROM orders\n",
"LIMIT 5;"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "47c21508",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"5 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" order_id | \n",
" product_id | \n",
" unit_price | \n",
" quantity | \n",
" discount | \n",
"
\n",
" \n",
" \n",
" \n",
" 10248 | \n",
" 11 | \n",
" 14.0 | \n",
" 12 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 10248 | \n",
" 42 | \n",
" 9.8 | \n",
" 10 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 10248 | \n",
" 72 | \n",
" 34.8 | \n",
" 5 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 10249 | \n",
" 14 | \n",
" 18.6 | \n",
" 9 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 10249 | \n",
" 51 | \n",
" 42.4 | \n",
" 40 | \n",
" 0.0 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(10248, 11, 14.0, 12, 0.0),\n",
" (10248, 42, 9.8, 10, 0.0),\n",
" (10248, 72, 34.8, 5, 0.0),\n",
" (10249, 14, 18.6, 9, 0.0),\n",
" (10249, 51, 42.4, 40, 0.0)]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT *\n",
"FROM order_details\n",
"LIMIT 5;"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "4c4afb57",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"5 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" product_id | \n",
" product_name | \n",
" supplier_id | \n",
" category_id | \n",
" quantity_per_unit | \n",
" unit_price | \n",
" units_in_stock | \n",
" units_on_order | \n",
" reorder_level | \n",
" discontinued | \n",
"
\n",
" \n",
" \n",
" \n",
" 1 | \n",
" Chai | \n",
" 8 | \n",
" 1 | \n",
" 10 boxes x 30 bags | \n",
" 18.0 | \n",
" 39 | \n",
" 0 | \n",
" 10 | \n",
" 1 | \n",
"
\n",
" \n",
" 2 | \n",
" Chang | \n",
" 1 | \n",
" 1 | \n",
" 24 - 12 oz bottles | \n",
" 19.0 | \n",
" 17 | \n",
" 40 | \n",
" 25 | \n",
" 1 | \n",
"
\n",
" \n",
" 3 | \n",
" Aniseed Syrup | \n",
" 1 | \n",
" 2 | \n",
" 12 - 550 ml bottles | \n",
" 10.0 | \n",
" 13 | \n",
" 70 | \n",
" 25 | \n",
" 0 | \n",
"
\n",
" \n",
" 4 | \n",
" Chef Anton's Cajun Seasoning | \n",
" 2 | \n",
" 2 | \n",
" 48 - 6 oz jars | \n",
" 22.0 | \n",
" 53 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
"
\n",
" \n",
" 5 | \n",
" Chef Anton's Gumbo Mix | \n",
" 2 | \n",
" 2 | \n",
" 36 boxes | \n",
" 21.35 | \n",
" 0 | \n",
" 0 | \n",
" 0 | \n",
" 1 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(1, 'Chai', 8, 1, '10 boxes x 30 bags', 18.0, 39, 0, 10, 1),\n",
" (2, 'Chang', 1, 1, '24 - 12 oz bottles', 19.0, 17, 40, 25, 1),\n",
" (3, 'Aniseed Syrup', 1, 2, '12 - 550 ml bottles', 10.0, 13, 70, 25, 0),\n",
" (4, \"Chef Anton's Cajun Seasoning\", 2, 2, '48 - 6 oz jars', 22.0, 53, 0, 0, 0),\n",
" (5, \"Chef Anton's Gumbo Mix\", 2, 2, '36 boxes', 21.35, 0, 0, 0, 1)]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT *\n",
"FROM products\n",
"LIMIT 5;"
]
},
{
"cell_type": "markdown",
"id": "83ace3dc",
"metadata": {},
"source": [
"Combine `orders` and `employees` tables to see who is responsible for each order:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "2e6d4d90",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"10 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" employee_name | \n",
" order_id | \n",
" order_date | \n",
"
\n",
" \n",
" \n",
" \n",
" Steven Buchanan | \n",
" 10248 | \n",
" 1996-07-04 | \n",
"
\n",
" \n",
" Michael Suyama | \n",
" 10249 | \n",
" 1996-07-05 | \n",
"
\n",
" \n",
" Margaret Peacock | \n",
" 10250 | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" Janet Leverling | \n",
" 10251 | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" Margaret Peacock | \n",
" 10252 | \n",
" 1996-07-09 | \n",
"
\n",
" \n",
" Janet Leverling | \n",
" 10253 | \n",
" 1996-07-10 | \n",
"
\n",
" \n",
" Steven Buchanan | \n",
" 10254 | \n",
" 1996-07-11 | \n",
"
\n",
" \n",
" Anne Dodsworth | \n",
" 10255 | \n",
" 1996-07-12 | \n",
"
\n",
" \n",
" Janet Leverling | \n",
" 10256 | \n",
" 1996-07-15 | \n",
"
\n",
" \n",
" Margaret Peacock | \n",
" 10257 | \n",
" 1996-07-16 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[('Steven Buchanan', 10248, datetime.date(1996, 7, 4)),\n",
" ('Michael Suyama', 10249, datetime.date(1996, 7, 5)),\n",
" ('Margaret Peacock', 10250, datetime.date(1996, 7, 8)),\n",
" ('Janet Leverling', 10251, datetime.date(1996, 7, 8)),\n",
" ('Margaret Peacock', 10252, datetime.date(1996, 7, 9)),\n",
" ('Janet Leverling', 10253, datetime.date(1996, 7, 10)),\n",
" ('Steven Buchanan', 10254, datetime.date(1996, 7, 11)),\n",
" ('Anne Dodsworth', 10255, datetime.date(1996, 7, 12)),\n",
" ('Janet Leverling', 10256, datetime.date(1996, 7, 15)),\n",
" ('Margaret Peacock', 10257, datetime.date(1996, 7, 16))]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT \n",
" e.first_name || ' ' || e.last_name as employee_name,\n",
" o.order_id,\n",
" o.order_date\n",
"FROM orders o\n",
"JOIN employees e ON o.employee_id = e.employee_id\n",
"LIMIT 10;"
]
},
{
"cell_type": "markdown",
"id": "66c9f902",
"metadata": {},
"source": [
"Combine `orders` and `customers` tables to get more detailed information about each customer:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "5b73e928",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"10 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" order_id | \n",
" company_name | \n",
" contact_name | \n",
" order_date | \n",
"
\n",
" \n",
" \n",
" \n",
" 10248 | \n",
" Vins et alcools Chevalier | \n",
" Paul Henriot | \n",
" 1996-07-04 | \n",
"
\n",
" \n",
" 10249 | \n",
" Toms Spezialitäten | \n",
" Karin Josephs | \n",
" 1996-07-05 | \n",
"
\n",
" \n",
" 10250 | \n",
" Hanari Carnes | \n",
" Mario Pontes | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" 10251 | \n",
" Victuailles en stock | \n",
" Mary Saveley | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" 10252 | \n",
" Suprêmes délices | \n",
" Pascale Cartrain | \n",
" 1996-07-09 | \n",
"
\n",
" \n",
" 10253 | \n",
" Hanari Carnes | \n",
" Mario Pontes | \n",
" 1996-07-10 | \n",
"
\n",
" \n",
" 10254 | \n",
" Chop-suey Chinese | \n",
" Yang Wang | \n",
" 1996-07-11 | \n",
"
\n",
" \n",
" 10255 | \n",
" Richter Supermarkt | \n",
" Michael Holz | \n",
" 1996-07-12 | \n",
"
\n",
" \n",
" 10256 | \n",
" Wellington Importadora | \n",
" Paula Parente | \n",
" 1996-07-15 | \n",
"
\n",
" \n",
" 10257 | \n",
" HILARION-Abastos | \n",
" Carlos Hernández | \n",
" 1996-07-16 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(10248, 'Vins et alcools Chevalier', 'Paul Henriot', datetime.date(1996, 7, 4)),\n",
" (10249, 'Toms Spezialitäten', 'Karin Josephs', datetime.date(1996, 7, 5)),\n",
" (10250, 'Hanari Carnes', 'Mario Pontes', datetime.date(1996, 7, 8)),\n",
" (10251, 'Victuailles en stock', 'Mary Saveley', datetime.date(1996, 7, 8)),\n",
" (10252, 'Suprêmes délices', 'Pascale Cartrain', datetime.date(1996, 7, 9)),\n",
" (10253, 'Hanari Carnes', 'Mario Pontes', datetime.date(1996, 7, 10)),\n",
" (10254, 'Chop-suey Chinese', 'Yang Wang', datetime.date(1996, 7, 11)),\n",
" (10255, 'Richter Supermarkt', 'Michael Holz', datetime.date(1996, 7, 12)),\n",
" (10256, 'Wellington Importadora', 'Paula Parente', datetime.date(1996, 7, 15)),\n",
" (10257, 'HILARION-Abastos', 'Carlos Hernández', datetime.date(1996, 7, 16))]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT \n",
" o.order_id,\n",
" c.company_name,\n",
" c.contact_name,\n",
" o.order_date\n",
"FROM orders o\n",
"JOIN customers c ON o.customer_id = c.customer_id\n",
"LIMIT 10;"
]
},
{
"cell_type": "markdown",
"id": "65dc2089",
"metadata": {},
"source": [
"Combine `order_details`, `products`, and `orders` to get detailed order information including the product name and quantity:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "eae620d2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"10 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" order_id | \n",
" product_name | \n",
" quantity | \n",
" order_date | \n",
"
\n",
" \n",
" \n",
" \n",
" 10248 | \n",
" Queso Cabrales | \n",
" 12 | \n",
" 1996-07-04 | \n",
"
\n",
" \n",
" 10248 | \n",
" Singaporean Hokkien Fried Mee | \n",
" 10 | \n",
" 1996-07-04 | \n",
"
\n",
" \n",
" 10248 | \n",
" Mozzarella di Giovanni | \n",
" 5 | \n",
" 1996-07-04 | \n",
"
\n",
" \n",
" 10249 | \n",
" Tofu | \n",
" 9 | \n",
" 1996-07-05 | \n",
"
\n",
" \n",
" 10249 | \n",
" Manjimup Dried Apples | \n",
" 40 | \n",
" 1996-07-05 | \n",
"
\n",
" \n",
" 10250 | \n",
" Jack's New England Clam Chowder | \n",
" 10 | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" 10250 | \n",
" Manjimup Dried Apples | \n",
" 35 | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" 10250 | \n",
" Louisiana Fiery Hot Pepper Sauce | \n",
" 15 | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" 10251 | \n",
" Gustaf's Knäckebröd | \n",
" 6 | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
" 10251 | \n",
" Ravioli Angelo | \n",
" 15 | \n",
" 1996-07-08 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(10248, 'Queso Cabrales', 12, datetime.date(1996, 7, 4)),\n",
" (10248, 'Singaporean Hokkien Fried Mee', 10, datetime.date(1996, 7, 4)),\n",
" (10248, 'Mozzarella di Giovanni', 5, datetime.date(1996, 7, 4)),\n",
" (10249, 'Tofu', 9, datetime.date(1996, 7, 5)),\n",
" (10249, 'Manjimup Dried Apples', 40, datetime.date(1996, 7, 5)),\n",
" (10250, \"Jack's New England Clam Chowder\", 10, datetime.date(1996, 7, 8)),\n",
" (10250, 'Manjimup Dried Apples', 35, datetime.date(1996, 7, 8)),\n",
" (10250, 'Louisiana Fiery Hot Pepper Sauce', 15, datetime.date(1996, 7, 8)),\n",
" (10251, \"Gustaf's Knäckebröd\", 6, datetime.date(1996, 7, 8)),\n",
" (10251, 'Ravioli Angelo', 15, datetime.date(1996, 7, 8))]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"SELECT \n",
" o.order_id,\n",
" p.product_name,\n",
" od.quantity,\n",
" o.order_date\n",
"FROM order_details od\n",
"JOIN products p ON od.product_id = p.product_id\n",
"JOIN orders o ON od.order_id = o.order_id\n",
"LIMIT 10;"
]
},
{
"cell_type": "markdown",
"id": "ae99ad83-81c2-40e3-bff9-0a549cc2307b",
"metadata": {},
"source": [
"#### Rank employees by sales performance"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "dadbbfb8-7d11-4c4b-88d6-0bd5bf32c2cc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"9 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" employee_id | \n",
" first_name | \n",
" last_name | \n",
" Sales Rank | \n",
"
\n",
" \n",
" \n",
" \n",
" 4 | \n",
" Margaret | \n",
" Peacock | \n",
" 1 | \n",
"
\n",
" \n",
" 3 | \n",
" Janet | \n",
" Leverling | \n",
" 2 | \n",
"
\n",
" \n",
" 1 | \n",
" Nancy | \n",
" Davolio | \n",
" 3 | \n",
"
\n",
" \n",
" 2 | \n",
" Andrew | \n",
" Fuller | \n",
" 4 | \n",
"
\n",
" \n",
" 8 | \n",
" Laura | \n",
" Callahan | \n",
" 5 | \n",
"
\n",
" \n",
" 7 | \n",
" Robert | \n",
" King | \n",
" 6 | \n",
"
\n",
" \n",
" 9 | \n",
" Anne | \n",
" Dodsworth | \n",
" 7 | \n",
"
\n",
" \n",
" 6 | \n",
" Michael | \n",
" Suyama | \n",
" 8 | \n",
"
\n",
" \n",
" 5 | \n",
" Steven | \n",
" Buchanan | \n",
" 9 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(4, 'Margaret', 'Peacock', 1),\n",
" (3, 'Janet', 'Leverling', 2),\n",
" (1, 'Nancy', 'Davolio', 3),\n",
" (2, 'Andrew', 'Fuller', 4),\n",
" (8, 'Laura', 'Callahan', 5),\n",
" (7, 'Robert', 'King', 6),\n",
" (9, 'Anne', 'Dodsworth', 7),\n",
" (6, 'Michael', 'Suyama', 8),\n",
" (5, 'Steven', 'Buchanan', 9)]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"WITH EmployeeSales AS (\n",
" SELECT Employees.Employee_ID, Employees.First_Name, Employees.Last_Name,\n",
" SUM(Unit_Price * Quantity * (1 - Discount)) AS \"Total Sales\"\n",
" FROM Orders \n",
" JOIN Order_Details ON Orders.Order_ID = Order_Details.Order_ID\n",
" JOIN Employees ON Orders.Employee_ID = Employees.Employee_ID\n",
"\n",
" GROUP BY Employees.Employee_ID\n",
")\n",
"SELECT Employee_ID, First_Name, Last_Name,\n",
" RANK() OVER (ORDER BY \"Total Sales\" DESC) AS \"Sales Rank\"\n",
"FROM EmployeeSales;\n"
]
},
{
"cell_type": "markdown",
"id": "6db4f6ea",
"metadata": {},
"source": [
"We can see that Margeret Peacock is the top-selling employee and Steven Buchanan is the lowest-selling employee."
]
},
{
"cell_type": "markdown",
"id": "edbf8c56-2cc9-434a-a992-bbae92d3858f",
"metadata": {},
"source": [
"#### Calculate running total of sales per month"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "8e9e175e-f00a-45ef-8829-c6b9d50422e3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"23 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" Month | \n",
" Running Total | \n",
"
\n",
" \n",
" \n",
" \n",
" 1996-07-01 | \n",
" 27861.89512966156 | \n",
"
\n",
" \n",
" 1996-08-01 | \n",
" 53347.17020040483 | \n",
"
\n",
" \n",
" 1996-09-01 | \n",
" 79728.57033299239 | \n",
"
\n",
" \n",
" 1996-10-01 | \n",
" 117244.29527847127 | \n",
"
\n",
" \n",
" 1996-11-01 | \n",
" 162844.3404896083 | \n",
"
\n",
" \n",
" 1996-12-01 | \n",
" 208083.97098282274 | \n",
"
\n",
" \n",
" 1997-01-01 | \n",
" 269342.0411508011 | \n",
"
\n",
" \n",
" 1997-02-01 | \n",
" 307825.6761011254 | \n",
"
\n",
" \n",
" 1997-03-01 | \n",
" 346372.8962108522 | \n",
"
\n",
" \n",
" 1997-04-01 | \n",
" 399405.8485997937 | \n",
"
\n",
" \n",
" 1997-05-01 | \n",
" 453187.13842493534 | \n",
"
\n",
" \n",
" 1997-06-01 | \n",
" 489549.9407597378 | \n",
"
\n",
" \n",
" 1997-07-01 | \n",
" 540570.7982783426 | \n",
"
\n",
" \n",
" 1997-08-01 | \n",
" 587858.4679665978 | \n",
"
\n",
" \n",
" 1997-09-01 | \n",
" 643487.7103683471 | \n",
"
\n",
" \n",
" 1997-10-01 | \n",
" 710236.9361440743 | \n",
"
\n",
" \n",
" 1997-11-01 | \n",
" 753770.7449116395 | \n",
"
\n",
" \n",
" 1997-12-01 | \n",
" 825169.1733755233 | \n",
"
\n",
" \n",
" 1998-01-01 | \n",
" 919391.2835824591 | \n",
"
\n",
" \n",
" 1998-02-01 | \n",
" 1018806.5709654673 | \n",
"
\n",
" \n",
" 1998-03-01 | \n",
" 1123660.7259656242 | \n",
"
\n",
" \n",
" 1998-04-01 | \n",
" 1247459.4082211715 | \n",
"
\n",
" \n",
" 1998-05-01 | \n",
" 1265793.0386533642 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(datetime.date(1996, 7, 1), 27861.89512966156),\n",
" (datetime.date(1996, 8, 1), 53347.17020040483),\n",
" (datetime.date(1996, 9, 1), 79728.57033299239),\n",
" (datetime.date(1996, 10, 1), 117244.29527847127),\n",
" (datetime.date(1996, 11, 1), 162844.3404896083),\n",
" (datetime.date(1996, 12, 1), 208083.97098282274),\n",
" (datetime.date(1997, 1, 1), 269342.0411508011),\n",
" (datetime.date(1997, 2, 1), 307825.6761011254),\n",
" (datetime.date(1997, 3, 1), 346372.8962108522),\n",
" (datetime.date(1997, 4, 1), 399405.8485997937),\n",
" (datetime.date(1997, 5, 1), 453187.13842493534),\n",
" (datetime.date(1997, 6, 1), 489549.9407597378),\n",
" (datetime.date(1997, 7, 1), 540570.7982783426),\n",
" (datetime.date(1997, 8, 1), 587858.4679665978),\n",
" (datetime.date(1997, 9, 1), 643487.7103683471),\n",
" (datetime.date(1997, 10, 1), 710236.9361440743),\n",
" (datetime.date(1997, 11, 1), 753770.7449116395),\n",
" (datetime.date(1997, 12, 1), 825169.1733755233),\n",
" (datetime.date(1998, 1, 1), 919391.2835824591),\n",
" (datetime.date(1998, 2, 1), 1018806.5709654673),\n",
" (datetime.date(1998, 3, 1), 1123660.7259656242),\n",
" (datetime.date(1998, 4, 1), 1247459.4082211715),\n",
" (datetime.date(1998, 5, 1), 1265793.0386533642)]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"-- Exe 1\n",
"WITH MonthlySales AS (\n",
" SELECT DATE_TRUNC('month', Order_Date)::DATE AS \"Month\", \n",
" SUM(Unit_Price * Quantity * (1 - Discount)) AS \"Total Sales\"\n",
" FROM Orders \n",
" JOIN Order_Details ON Orders.Order_ID = Order_Details.Order_ID\n",
" GROUP BY DATE_TRUNC('month', Order_Date)\n",
")\n",
"SELECT \"Month\", \n",
" SUM(\"Total Sales\") OVER (ORDER BY \"Month\") AS \"Running Total\"\n",
"FROM MonthlySales\n",
"ORDER BY \"Month\";"
]
},
{
"cell_type": "markdown",
"id": "d5166f84-40eb-4b26-ab40-c902b3612c1a",
"metadata": {},
"source": [
"#### Calculate the month-over-month sales growth rate"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "8c0c051c-7e44-4746-8a6d-8c2d73a624f3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"23 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" year | \n",
" month | \n",
" Growth Rate | \n",
"
\n",
" \n",
" \n",
" \n",
" 1996 | \n",
" 7 | \n",
" None | \n",
"
\n",
" \n",
" 1996 | \n",
" 8 | \n",
" -8.530001451294545 | \n",
"
\n",
" \n",
" 1996 | \n",
" 9 | \n",
" 3.51624637896504 | \n",
"
\n",
" \n",
" 1996 | \n",
" 10 | \n",
" 42.20520805162909 | \n",
"
\n",
" \n",
" 1996 | \n",
" 11 | \n",
" 21.54915112904513 | \n",
"
\n",
" \n",
" 1996 | \n",
" 12 | \n",
" -0.7903823696967553 | \n",
"
\n",
" \n",
" 1997 | \n",
" 1 | \n",
" 35.40798079057388 | \n",
"
\n",
" \n",
" 1997 | \n",
" 2 | \n",
" -37.17785290199861 | \n",
"
\n",
" \n",
" 1997 | \n",
" 3 | \n",
" 0.16522649038887202 | \n",
"
\n",
" \n",
" 1997 | \n",
" 4 | \n",
" 37.579187910257275 | \n",
"
\n",
" \n",
" 1997 | \n",
" 5 | \n",
" 1.4110800973551207 | \n",
"
\n",
" \n",
" 1997 | \n",
" 6 | \n",
" -32.38763433709323 | \n",
"
\n",
" \n",
" 1997 | \n",
" 7 | \n",
" 40.31057631048775 | \n",
"
\n",
" \n",
" 1997 | \n",
" 8 | \n",
" -7.316983704141531 | \n",
"
\n",
" \n",
" 1997 | \n",
" 9 | \n",
" 17.64005874784288 | \n",
"
\n",
" \n",
" 1997 | \n",
" 10 | \n",
" 19.98945679265288 | \n",
"
\n",
" \n",
" 1997 | \n",
" 11 | \n",
" -34.780054357730286 | \n",
"
\n",
" \n",
" 1997 | \n",
" 12 | \n",
" 64.00685004404939 | \n",
"
\n",
" \n",
" 1998 | \n",
" 1 | \n",
" 31.966644412344674 | \n",
"
\n",
" \n",
" 1998 | \n",
" 2 | \n",
" 5.511633272346428 | \n",
"
\n",
" \n",
" 1998 | \n",
" 3 | \n",
" 5.47085640480519 | \n",
"
\n",
" \n",
" 1998 | \n",
" 4 | \n",
" 18.06750267107856 | \n",
"
\n",
" \n",
" 1998 | \n",
" 5 | \n",
" -85.1907709370056 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(Decimal('1996'), Decimal('7'), None),\n",
" (Decimal('1996'), Decimal('8'), -8.530001451294545),\n",
" (Decimal('1996'), Decimal('9'), 3.51624637896504),\n",
" (Decimal('1996'), Decimal('10'), 42.20520805162909),\n",
" (Decimal('1996'), Decimal('11'), 21.54915112904513),\n",
" (Decimal('1996'), Decimal('12'), -0.7903823696967553),\n",
" (Decimal('1997'), Decimal('1'), 35.40798079057388),\n",
" (Decimal('1997'), Decimal('2'), -37.17785290199861),\n",
" (Decimal('1997'), Decimal('3'), 0.16522649038887202),\n",
" (Decimal('1997'), Decimal('4'), 37.579187910257275),\n",
" (Decimal('1997'), Decimal('5'), 1.4110800973551207),\n",
" (Decimal('1997'), Decimal('6'), -32.38763433709323),\n",
" (Decimal('1997'), Decimal('7'), 40.31057631048775),\n",
" (Decimal('1997'), Decimal('8'), -7.316983704141531),\n",
" (Decimal('1997'), Decimal('9'), 17.64005874784288),\n",
" (Decimal('1997'), Decimal('10'), 19.98945679265288),\n",
" (Decimal('1997'), Decimal('11'), -34.780054357730286),\n",
" (Decimal('1997'), Decimal('12'), 64.00685004404939),\n",
" (Decimal('1998'), Decimal('1'), 31.966644412344674),\n",
" (Decimal('1998'), Decimal('2'), 5.511633272346428),\n",
" (Decimal('1998'), Decimal('3'), 5.47085640480519),\n",
" (Decimal('1998'), Decimal('4'), 18.06750267107856),\n",
" (Decimal('1998'), Decimal('5'), -85.1907709370056)]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"WITH MonthlySales AS (\n",
" SELECT EXTRACT('month' from Order_Date) AS Month, \n",
" EXTRACT('year' from Order_Date) AS Year, \n",
" SUM(Unit_Price * Quantity * (1 - Discount)) AS TotalSales\n",
" FROM Orders \n",
" JOIN Order_Details ON Orders.Order_ID = Order_Details.Order_ID\n",
" GROUP BY EXTRACT('month' from Order_Date), EXTRACT('year' from Order_Date)\n",
"),\n",
"LaggedSales AS (\n",
" SELECT Month, Year, \n",
" TotalSales, \n",
" LAG(TotalSales) OVER (ORDER BY Year, Month) AS PreviousMonthSales\n",
" FROM MonthlySales\n",
")\n",
"SELECT Year, Month,\n",
" ((TotalSales - PreviousMonthSales) / PreviousMonthSales) * 100 AS \"Growth Rate\"\n",
"FROM LaggedSales;\n"
]
},
{
"cell_type": "markdown",
"id": "79ca1e3b-26a5-4701-9217-b77b4f494cd5",
"metadata": {},
"source": [
"#### Identify customers with above-average order values"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "5df0d97a-15c8-42db-911d-7cbe7ce2502e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"10 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" customer_id | \n",
" order_id | \n",
" Order Value | \n",
" Value Category | \n",
"
\n",
" \n",
" \n",
" \n",
" VINET | \n",
" 10248 | \n",
" 439.99999809265137 | \n",
" Below Average | \n",
"
\n",
" \n",
" TOMSP | \n",
" 10249 | \n",
" 1863.4000644683838 | \n",
" Above Average | \n",
"
\n",
" \n",
" HANAR | \n",
" 10250 | \n",
" 1552.600023412704 | \n",
" Above Average | \n",
"
\n",
" \n",
" VICTE | \n",
" 10251 | \n",
" 654.0599855789542 | \n",
" Below Average | \n",
"
\n",
" \n",
" SUPRD | \n",
" 10252 | \n",
" 3597.9001445159315 | \n",
" Above Average | \n",
"
\n",
" \n",
" HANAR | \n",
" 10253 | \n",
" 1444.7999839782715 | \n",
" Below Average | \n",
"
\n",
" \n",
" CHOPS | \n",
" 10254 | \n",
" 556.62000967741 | \n",
" Below Average | \n",
"
\n",
" \n",
" RICSU | \n",
" 10255 | \n",
" 2490.4999780654907 | \n",
" Above Average | \n",
"
\n",
" \n",
" WELLI | \n",
" 10256 | \n",
" 517.8000068664551 | \n",
" Below Average | \n",
"
\n",
" \n",
" HILAA | \n",
" 10257 | \n",
" 1119.899953842163 | \n",
" Below Average | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[('VINET', 10248, 439.99999809265137, 'Below Average'),\n",
" ('TOMSP', 10249, 1863.4000644683838, 'Above Average'),\n",
" ('HANAR', 10250, 1552.600023412704, 'Above Average'),\n",
" ('VICTE', 10251, 654.0599855789542, 'Below Average'),\n",
" ('SUPRD', 10252, 3597.9001445159315, 'Above Average'),\n",
" ('HANAR', 10253, 1444.7999839782715, 'Below Average'),\n",
" ('CHOPS', 10254, 556.62000967741, 'Below Average'),\n",
" ('RICSU', 10255, 2490.4999780654907, 'Above Average'),\n",
" ('WELLI', 10256, 517.8000068664551, 'Below Average'),\n",
" ('HILAA', 10257, 1119.899953842163, 'Below Average')]"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"WITH OrderValues AS (\n",
" SELECT Orders.Customer_ID, \n",
" Orders.Order_ID, \n",
" SUM(Unit_Price * Quantity * (1 - Discount)) AS \"Order Value\"\n",
" FROM Orders \n",
" JOIN Order_Details ON Orders.Order_ID = Order_Details.Order_ID\n",
" GROUP BY Orders.Customer_ID, Orders.Order_ID\n",
")\n",
"SELECT Customer_ID, \n",
" Order_ID, \n",
" \"Order Value\",\n",
" CASE \n",
" WHEN \"Order Value\" > AVG(\"Order Value\") OVER () THEN 'Above Average'\n",
" ELSE 'Below Average'\n",
" END AS \"Value Category\"\n",
"FROM OrderValues LIMIT 10;"
]
},
{
"cell_type": "markdown",
"id": "bb025688-fc4f-42ab-b5d9-f46f05a61702",
"metadata": {},
"source": [
"#### Calculate the percentage of total sales for each product category"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "be6b4eba-3bc8-44e4-9c4c-cc0483fb7736",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"8 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" category_id | \n",
" category_name | \n",
" Sales Percentage | \n",
"
\n",
" \n",
" \n",
" \n",
" 8 | \n",
" Seafood | \n",
" 10.195732374296789 | \n",
"
\n",
" \n",
" 7 | \n",
" Produce | \n",
" 7.813322138303922 | \n",
"
\n",
" \n",
" 1 | \n",
" Beverages | \n",
" 21.331025404054813 | \n",
"
\n",
" \n",
" 5 | \n",
" Grains/Cereals | \n",
" 7.510473482122698 | \n",
"
\n",
" \n",
" 2 | \n",
" Condiments | \n",
" 8.400470714786334 | \n",
"
\n",
" \n",
" 4 | \n",
" Dairy Products | \n",
" 18.556754766640605 | \n",
"
\n",
" \n",
" 6 | \n",
" Meat/Poultry | \n",
" 12.902483709246834 | \n",
"
\n",
" \n",
" 3 | \n",
" Confections | \n",
" 13.289737410548023 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(8, 'Seafood', 10.195732374296789),\n",
" (7, 'Produce', 7.813322138303922),\n",
" (1, 'Beverages', 21.331025404054813),\n",
" (5, 'Grains/Cereals', 7.510473482122698),\n",
" (2, 'Condiments', 8.400470714786334),\n",
" (4, 'Dairy Products', 18.556754766640605),\n",
" (6, 'Meat/Poultry', 12.902483709246834),\n",
" (3, 'Confections', 13.289737410548023)]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"WITH CategorySales AS (\n",
" SELECT Categories.Category_ID, Categories.Category_Name,\n",
" SUM(Products.Unit_Price * Quantity * (1 - Discount)) AS \"Total Sales\"\n",
" FROM Categories\n",
" JOIN Products ON Categories.Category_ID = Products.Category_ID\n",
" JOIN Order_Details ON Products.Product_ID = Order_Details.Product_ID\n",
" GROUP BY Categories.Category_ID\n",
")\n",
"SELECT Category_ID, Category_Name,\n",
" \"Total Sales\" / SUM(\"Total Sales\") OVER () * 100 AS \"Sales Percentage\"\n",
"FROM CategorySales;"
]
},
{
"cell_type": "markdown",
"id": "8df728df",
"metadata": {},
"source": [
"Beverages is the top category in terms of sales percentages, followed closely by Dairy Products. Produce and Grains/Cereals are the categories with the smallest sales percentage."
]
},
{
"cell_type": "markdown",
"id": "e4a23afd-0407-4513-812e-311b0a3f65a2",
"metadata": {},
"source": [
"#### Find the top 3 products sold in each category"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "cae98dcd-1cec-4847-a73b-553b8d1f41aa",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" * postgresql://postgres:***@localhost:5432/northwind\n",
"24 rows affected.\n"
]
},
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" category_id | \n",
" product_id | \n",
" product_name | \n",
" Total Sales | \n",
"
\n",
" \n",
" \n",
" \n",
" 1 | \n",
" 38 | \n",
" Côte de Blaye | \n",
" 153897.1748863291 | \n",
"
\n",
" \n",
" 1 | \n",
" 43 | \n",
" Ipoh Coffee | \n",
" 25109.09997367859 | \n",
"
\n",
" \n",
" 1 | \n",
" 2 | \n",
" Chang | \n",
" 17719.399970583618 | \n",
"
\n",
" \n",
" 2 | \n",
" 63 | \n",
" Vegie-spread | \n",
" 18343.61561246872 | \n",
"
\n",
" \n",
" 2 | \n",
" 61 | \n",
" Sirop d'érable | \n",
" 15022.349960759282 | \n",
"
\n",
" \n",
" 2 | \n",
" 65 | \n",
" Louisiana Fiery Hot Pepper Sauce | \n",
" 14893.926944906489 | \n",
"
\n",
" \n",
" 3 | \n",
" 62 | \n",
" Tarte au sucre | \n",
" 50737.09416846588 | \n",
"
\n",
" \n",
" 3 | \n",
" 20 | \n",
" Sir Rodney's Marmalade | \n",
" 24199.559986554086 | \n",
"
\n",
" \n",
" 3 | \n",
" 26 | \n",
" Gumbär Gummibärchen | \n",
" 21662.689146941742 | \n",
"
\n",
" \n",
" 4 | \n",
" 59 | \n",
" Raclette Courdavault | \n",
" 76683.74989898875 | \n",
"
\n",
" \n",
" 4 | \n",
" 60 | \n",
" Camembert Pierrot | \n",
" 49877.31995112449 | \n",
"
\n",
" \n",
" 4 | \n",
" 72 | \n",
" Mozzarella di Giovanni | \n",
" 27086.57939014256 | \n",
"
\n",
" \n",
" 5 | \n",
" 56 | \n",
" Gnocchi di nonna Alice | \n",
" 45351.09995948523 | \n",
"
\n",
" \n",
" 5 | \n",
" 64 | \n",
" Wimmers gute Semmelknödel | \n",
" 23487.467487137765 | \n",
"
\n",
" \n",
" 5 | \n",
" 42 | \n",
" Singaporean Hokkien Fried Mee | \n",
" 8986.599987879395 | \n",
"
\n",
" \n",
" 6 | \n",
" 29 | \n",
" Thüringer Rostbratwurst | \n",
" 84783.77159642408 | \n",
"
\n",
" \n",
" 6 | \n",
" 17 | \n",
" Alice Mutton | \n",
" 35105.849979020655 | \n",
"
\n",
" \n",
" 6 | \n",
" 53 | \n",
" Perth Pasties | \n",
" 22623.799456167217 | \n",
"
\n",
" \n",
" 7 | \n",
" 51 | \n",
" Manjimup Dried Apples | \n",
" 43846.89994909987 | \n",
"
\n",
" \n",
" 7 | \n",
" 28 | \n",
" Rössle Sauerkraut | \n",
" 27936.839044377804 | \n",
"
\n",
" \n",
" 7 | \n",
" 7 | \n",
" Uncle Bob's Organic Dried Pears | \n",
" 22453.49998757243 | \n",
"
\n",
" \n",
" 8 | \n",
" 18 | \n",
" Carnarvon Tigers | \n",
" 30728.12496125698 | \n",
"
\n",
" \n",
" 8 | \n",
" 10 | \n",
" Ikura | \n",
" 21653.499964892864 | \n",
"
\n",
" \n",
" 8 | \n",
" 40 | \n",
" Boston Crab Meat | \n",
" 19055.039585784674 | \n",
"
\n",
" \n",
"
"
],
"text/plain": [
"[(1, 38, 'Côte de Blaye', 153897.1748863291),\n",
" (1, 43, 'Ipoh Coffee', 25109.09997367859),\n",
" (1, 2, 'Chang', 17719.399970583618),\n",
" (2, 63, 'Vegie-spread', 18343.61561246872),\n",
" (2, 61, \"Sirop d'érable\", 15022.349960759282),\n",
" (2, 65, 'Louisiana Fiery Hot Pepper Sauce', 14893.926944906489),\n",
" (3, 62, 'Tarte au sucre', 50737.09416846588),\n",
" (3, 20, \"Sir Rodney's Marmalade\", 24199.559986554086),\n",
" (3, 26, 'Gumbär Gummibärchen', 21662.689146941742),\n",
" (4, 59, 'Raclette Courdavault', 76683.74989898875),\n",
" (4, 60, 'Camembert Pierrot', 49877.31995112449),\n",
" (4, 72, 'Mozzarella di Giovanni', 27086.57939014256),\n",
" (5, 56, 'Gnocchi di nonna Alice', 45351.09995948523),\n",
" (5, 64, 'Wimmers gute Semmelknödel', 23487.467487137765),\n",
" (5, 42, 'Singaporean Hokkien Fried Mee', 8986.599987879395),\n",
" (6, 29, 'Thüringer Rostbratwurst', 84783.77159642408),\n",
" (6, 17, 'Alice Mutton', 35105.849979020655),\n",
" (6, 53, 'Perth Pasties', 22623.799456167217),\n",
" (7, 51, 'Manjimup Dried Apples', 43846.89994909987),\n",
" (7, 28, 'Rössle Sauerkraut', 27936.839044377804),\n",
" (7, 7, \"Uncle Bob's Organic Dried Pears\", 22453.49998757243),\n",
" (8, 18, 'Carnarvon Tigers', 30728.12496125698),\n",
" (8, 10, 'Ikura', 21653.499964892864),\n",
" (8, 40, 'Boston Crab Meat', 19055.039585784674)]"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%sql\n",
"WITH ProductSales AS (\n",
" SELECT Products.Category_ID, \n",
" Products.Product_ID, Products.Product_Name,\n",
" SUM(Products.Unit_Price * Quantity * (1 - Discount)) AS \"Total Sales\"\n",
" FROM Products\n",
" JOIN Order_Details ON Products.Product_ID = Order_Details.Product_ID\n",
" GROUP BY Products.Category_ID, Products.Product_ID\n",
")\n",
"SELECT Category_ID, \n",
" Product_ID, Product_Name,\n",
" \"Total Sales\"\n",
"FROM (\n",
" SELECT Category_ID, \n",
" Product_ID, Product_Name,\n",
" \"Total Sales\", \n",
" ROW_NUMBER() OVER (PARTITION BY Category_ID ORDER BY \"Total Sales\" DESC) AS rn\n",
" FROM ProductSales\n",
") tmp\n",
"WHERE rn <= 3;\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}