Repository navigation
Expand file tree
/
Copy pathPostGreSQL-Commands.sql
More file actions
7710 lines (6731 loc) · 302 KB
/
Copy pathPostGreSQL-Commands.sql
File metadata and controls
7710 lines (6731 loc) · 302 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-- NOTE: We use Northwind db unless otherwise stated
-- How to list all the available tables in a database?
-- https://stackoverflow.com/questions/14730228/postgresql-query-to-list-all-table-names
SELECT table_name
FROM information_schema.tables
WHERE table_type='BASE TABLE'
AND table_schema='public';
-- Lecture 5:
DROP DATABASE "AdventureWorks" WITH (FORCE);
-- Section 3: Simple Selection Of All Records
-- Lecture 6: Selecting All Data From A Table
select * from customers;
-- Lecture 7: Selecting specific fields
-- How to get the schema for a specific table (e.g. suppliers)
select *
from information_schema.columns
where table_name = 'suppliers';
-- Get companyname, city and country fields from suppliers table
select companyname, city, country from suppliers;
-- Get categoryname and description fields from categories table
select categoryname, description from categories;
-- Lecture 8: Selecting Distinct Values
-- List all of the customers' countries (without duplicates)?
select distinct country from customers
-- List all of the customers' city & countries (without duplicates)?
select distinct city, country from customers
-- What are the unique regions our suppliers are in?
select distinct region from suppliers
-- Lecture 9: Counting results
-- How many entries do we have in products table?
select count(*) from products;
-- How many orders have we had so far?
select count(*) from orders;
-- How many cities are our Suppliers in?
select count(*) from (select distinct city from suppliers) as T; -- or
select count(distinct city) from suppliers;
-- How many distinct products have been ordered (hint. use order details table)
select count(distinct productid) from order_details;
-- Lecture 10: Combining fields in SELECT
-- List customerid and difference between shippeddate and orderdate for all our orders
select customerid, shippeddate - orderdate as delta from orders;
-- List order_id and the amount spent using order_details (unitprice times quantity minus discount)
select orderid, ((unitprice * quantity) - discount) as amount_spent from order_details
-- Lecture 11: Practice what you learned
-- NOTE: At this lecture, we use pagila database
-- Select all fields, and all records from actor table
select * from actor;
-- Select all fields and records from film table
select * from film;
-- Select all fields and records from the staff table
select * from staff;
-- Select address and district columns from address table
select address, district from address;
-- Select title and description from film table
select title, description from film;
-- Select city and country_id from city table
select city, country_id from city;
-- Select all the distinct last names from customer table
select distinct last_name from customer;
-- Select all the distinct first_names from the actor table
select distinct first_name from actor;
-- Select all the distinct inventory_id values from rental table
select distinct inventory_id from rental;
-- Find the number of films ( COUNT ).
select count(*) from film;
-- Find the number of categories.
select count(*) from category;
-- Find the number of distinct first_names in actor table
select count(distinct first_name) from actor;
-- Find the number of distinct (first_name, last_name) pairs
select count(distinct(first_name, last_name)) from actor;
-- Select rental_id and the difference between return_date and rental_date in rental table
select rental_id, return_date - rental_date as diff from rental;
-- Section 4: What if you dont want all records? Using WHERE to select records
-- Lecture 13: Searching for specific text
where customer_name='David Brown'
-- What if your text contains single quotes itself?
where title='Drop Can''t, Embrace Can'
-- NOTE: In PostGreSQL, you can't use double quotes to limit a string. Double quotes have other usage in PostGreSQL
-- NOTE: We use Northwind db unless otherwise stated
-- All my suppliers from Berlin
select * from suppliers where city = 'Berlin'
-- Find all customer companynames and the lead contactnames in Mexico
select companyname, contactname from customers where country='Mexico';
-- Lecture 14: Searching Numeric fields
-- Find the number of orders by employee with id of 3 (Janet Levering)
select count(*) from orders where employeeid = 3;
-- Number of order details that had more than 20 items ordered
select count(*) from order_details where quantity > 20;
-- How many orders had a freight cost equal to or greater than 250$
select count(*) from orders where freight >= 250;
-- Lecture 15: Searching DATE fields
-- Basic Syntax for Date Fields
where orderdate = '1996-07-04'
where orderdate > '1996-07-04'
where orderdate >= '1996-07-04'
where orderdate < '1996-07-04'
where orderdate <= '1996-07-04'
-- How to determine the current clock and the format of datetime based on your systems locale?
select now() --> 2020-10-19 15:33:12.096909+03
-- Find Number of Orders ordered on or after Jan 01, 1998
select count(*) from orders where orderdate >= '1998-01-01';
select count(*) from orders where orderdate >= date('Jan-01-1998');
-- How many orders shipped before July 5, 1997
select count(*) from orders where shippeddate < '1997-07-05';
select count(*) from orders where shippeddate < date('July-5-1997');
-- Lecture 16: WHERE using logical AND operator
-- Basic Syntax:
-- select <colun1>, <column2>, ... from <table_name>
-- where condition 1 and condition 2 and condition 3 and ...
-- How many orders shipped to Germany with fright cost more than 100$
select count(*) from orders where shipcountry='Germany' and freight>100;
-- We want the distict customers where orders were shipped shipped via United Package (id = 2)
-- and the ship country is Brazil
select distinct(customerid) from orders where shipvia=2 and shipcountry='Brazil'
-- Lecture 17: WHERE using logical OR operator
-- Basic Syntax:
-- select <colun1>, <column2>, ... from <table_name>
-- where condition 1 or condition 2 or condition 3 or ...
-- How many customers do we have in USA and Canada
select count(*) from customers where country='USA' or country='Canada';
select * from customers where country = 'USA' or country = 'Canada';
-- How many suppliers do we have in Germany and Spain
select count(*) from suppliers where country='Germany' or country='Spain';
select count(*) from suppliers where country in ('Germany', 'Spain');
-- How many orders shipped to USA, Brazil and Argentina
select count(*) from orders where shipcountry in ('USA', 'Brazil', 'Argentina');
-- Lecture 18: WHERE using logical NOT operator
-- Basic Syntax:
-- select <colun1>, <column2>, ... from <table_name>
-- where NOT <condition>
-- IMPORTANT: In postgres, unlike MySQL, string searching operations are case-sensitive by default
-- How many customers are not in France
select count(*) from customers where not country='France';
select count(*) from customers where country != 'France';
-- How many suppliers are not in USA
select count(*) from suppliers where not country='USA'
select count(*) from suppliers where country!='USA'
-- Lecture 19: WHERE combining AND, OR and NOT
-- Basic Syntax:
-- select <colun1>, <column2>, ... from <table_name>
-- where not ((<condition1> and not <condition2>) or <condition3>)
-- How many orders are shipped to Germany and freight charges < 50 or > 175
select count(*) from orders where shipcountry='Germany' and (freight < 50 or freight > 175);
select count(*) from orders where shipcountry = 'Germany' and not (freight >= 50 and freight <= 175);
-- How many orders shipped to Canada or Spain and shippeddate after May 1, 1997
select count(*) from orders where (shipcountry='Canada' or shipcountry='Spain') and shippeddate > '1997-05-01';
select count(*) from orders where shipcountry in ('Canada', 'Spain') and shippeddate > date('May-1-1997');
-- Lecture 20 : Using BETWEEN
-- where freight between 50 and 100
-- This is the same as:
-- where fright >= 50 and freight <= 100
-- How many order details have a unit price between $10 and $20
select count(*) from order_details where unitprice between 10 and 20;
-- How many orders shipped between June 1, 1996 and Sept 30, 1996
select count(*) from orders where shippeddate between '1996-06-01' and '1996-09-30';
select count(*) from orders where shippeddate between date('Jun-1-1996') and date('Sept-30-1996');
-- Lecture 21 : Using IN
-- Basic Syntax
-- where id in (22, 3, 5, 7)
-- or
-- where id = 22 or id = 3 or id = 5 or id = 7
-- How many suppliers are located in Germany, France, Spain or Italy
select count(*) from suppliers where country in ('Germany', 'France', 'Spain', 'Italy')
-- How many products do we have in categoryid 1,4,6 or 7
select count(*) from products where categoryid in (1, 4, 6, 7)
-- Lecture 22
-- Select all records from data_src which came from the journal named 'Food Chemistry'.
select * from data_src where journal='Food Chemistry';
-- Select record from nutr_def where nutrdesc is Retinol.
select * from nutr_def where nutrdesc = 'Retinol';
-- Find all the food descriptions (food_des) records for manufacturer Kellogg, Co.
-- (must include punctuation for exact match).
select * from food_des where manufacname='Kellogg, Co.';
-- Find the number of records in data sources (data_src) that were published after year 2000 (it is numeric field).
select count(*) from data_src where year > 2000;
-- Find the number of records in food description that have a fat_factor < 4.
select count(*) from food_des where fat_factor < 4;
-- Select all records from weight table that have gm_weight of 190.
select * from weight where gm_wgt = 190.0;
-- Find the number of records in food description table that have pro_factor greater than 1.5 and fat_factor less than 5.
select * from food_des where pro_factor > 1.5 and fat_factor < 5;
-- Find the record in data source table that is from year 1990 and the journal Cereal Foods World.
select * from data_src where year = 1990 and journal = 'Cereal Foods World';
-- Select count of weights where gm_wgt is greater than 150 and less than 200.
select count(*) from weight where gm_wgt > 150 and gm_wgt < 200;
-- Select the records in nutr_def table (nutrition definitions) that have units of kj or kcal.
select * from nutr_def where units in ('kj', 'kcal');
-- Select all records from data source table (data_src) that where from the year 2000 or the journal Food Chemistry.
select * from data_src where year = 2000 and journal = 'Food Chemistry';
-- How many records in food_des are not about food group Breakfast Cereals.
-- The field fdgrp_cd is an id field and you will have to find it in fd_group for fddrp_desc = 'Breakfast Cereals'.
select count(*) from food_des where fdgrp_cd != (select distinct fdgrp_cd from fd_group where fddrp_desc = 'Breakfast Cereals');
select count(*) from food_des left join fd_group using(fdgrp_cd) where not fddrp_desc = 'Breakfast Cereals';
-- Find all the records in data sources that where between 1990 and 2000 and either 'J. Food Protection' or 'Food Chemistry'.
select * from data_src where (year between 1990 and 2000) and (journal in ('J. Food Protection', 'Food Chemistry'))
-- Use BETWEEN syntax to find number of weight records that weight between 50 and 75 grams (gm_wgt).
select * from weight where gm_wgt between 50 and 75;
-- Select all records from the data source table that were published
-- in years 1960,1970,1980,1990, and 2000. Use the IN syntax.
select * from data_src where year in (1960,1970,1980,1990, 2000);
-- Lecture 23 : Schema Basics
-- Q) What is PostgreSQL schema?
-- A) In PostgreSQL, a schema is a namespace that contains named database objects such as tables.
-- views, indexes, data types, functions, stored procedures and operators. To access an object in a schema,
-- you need to qualify the object by using the following syntax: schema_name.object_name.
-- Reference: https://www.postgresqltutorial.com/postgresql-schema/
-- Select everything from product table in production schema
select * from production.product
-- Select verything from the vendor table in purchasing schema
select * from purchasing.vendor
-- Q) How to query vendor table's table schema?
select column_name, data_type, character_maximum_length, column_default, is_nullable
from INFORMATION_SCHEMA.COLUMNS where table_name = 'vendor';
-- Section 6: Using psql to connect to PostGres
-- Lecture 24: Connecting with psql
-- Basic syntax
psql --port=5433 --host=localhost --dbname=northwind --username=postgres
-- Lecture 26 & 27: psql commands
-- listing databases: \l
-- clearing screen: \! clear
-- how to switch to another database while logged in: \c AdventureWorks
-- See list of schemas: \dn
-- List all tables under a schema : \dt <schema name>. : e.g. \dt sales.
-- List entries inside a table under a schema: select * from sales.store limit 1;
-- Lecture 28: ORDER BY
-- Syntax:
-- select <column1>, <column2> from <table_name>
-- order by column1, column2, ... ASC|DESC
-- NOTE: We use Northwind db unless otherwise stated
-- List of countries of suppliers in ascending alphabetical order
select distinct(country) from suppliers order by country asc
-- List of countries and their cities of suppliers in ascending alphabetical order
select distinct country, city from suppliers order by country, city asc
-- Get a list of product names and unit prices
-- order by price highest to lowest
-- and the product names from a to z
select productname, unitprice from products
order by unitprice desc, productname asc;
-- Lecture 29: MIN & MAX
-- Syntax:
-- select min(column) from <table_name> where <condition>
-- select max(column) from <table_name> where <condition>
-- When was the first order ordered from Italy
select min(orderdate) from orders where shipcountry='Italy';
-- When was the last order shipped to Canada?
select max(shippeddate) from orders where shipcountry = 'Canada';
-- Find the longest period between ship date and order date:
select max(shippeddate-orderdate) from orders where shipcountry = 'France' and shippeddate is not null and orderdate is not null;
-- Find the slowest order sent to France based on order date vs. ship date
select * from orders where shipcountry = 'France' and shippeddate is not null and orderdate is not null
order by (shippeddate-orderdate) desc limit 1;
-- OR
select * from orders
where (shippeddate-orderdate) = (
select max(shippeddate-orderdate) from orders where shipcountry = 'France' and shippeddate is not null and orderdate is not null
) and shipcountry = 'France';
-- Lecture 30: AVG and SUM
-- Syntax:
-- select avg(column) from <table_name> where <condition>
-- select sum(column) from <table_name> where <condition>
-- What was average freight of orders shipped to Brazil
select avg(freight) from orders where shipcountry='Brazil';
-- How many individual items of Tofu (productid=14) were ordered
select sum(quantity) from order_details where productid = (select productid from products where productname='Tofu');
select sum(quantity) from products inner join order_details using(productid) where productname='Tofu';
-- What was the average number of Steeleye Stout (productid=35) per order
select avg(quantity) as avg_quantity from order_details
where productid = (
select productid from products where productname='Steeleye Stout'
);
-- OR
select avg(quantity) as avg_quantity from products inner join order_details using(productid)
where productname='Steeleye Stout';
-- Lecture 31: LIKE to match patterns
-- Syntax:
-- select <column1>, <column2>, ... from <table_name>
-- where <column> LIKE <pattern>
-- pattern is case sensitive
-- % stands for zero, one or more characters
-- _ stands for any single character
-- what customers have a contact whose first name starts with D?
select * from customers where contactname like 'D%'
-- Which of our suppliers have 'or' as the 2.nd and 3.rd letters in the company name?
select companyname from suppliers where companyname like '_or%'
-- Which customer company names end in 'er'?
select companyname from customers where companyname like '%er'
-- Lecture 32: Renaming columns using AS alias
-- Syntax
-- Select <column1> as alias_name from <table_name>
-- list the total amount spent per order details
select ((unitprice*quantity)-discount) as total_amount_spent from order_details;
-- list the total amount spent per order details & order it by total amount spent in asc fashion
select ((unitprice*quantity)-discount) as total_amount_spent from order_details
order by total_amount_spent asc;
-- calculate our inventory value of products
-- (need unitprice and unitsinstock fields)
-- and return as total_inventory
-- order by this column desc
select productid, productname, unitprice*unitsinstock as inventory_value from products
order by inventory_value desc;
-- Lecture 33: LIMIT the number of records returned
-- Syntax: select <column1>, <column2> ... from <table_name> limit number
-- Find 3 most expensive order details
select *, ((unitprice*quantity)-discount) as total_spent from order_details order by total_spent desc limit 3;
-- List the 2 products with the least inventory in stock by total dollar amount of inventory
select *, (unitprice*unitsinstock) as total_dollar_amount from products order by total_dollar_amount asc limit 2;
-- Lecture 34: NULL value
-- NULL is a special value that signifies unknown
-- not 0, not empty
-- Syntax for searching null:
-- select <column1>, <column2> from table_name where <columnX> is null
-- select <column1>, <column2> from table_name where <columnX> is not null
-- How many customers dont have a region value?
select count(*) from customers where region is null;
-- How many suppliers have a region value?
select count(*) from suppliers where region is not null;
-- How many orders did not have a ship region?
select count(*) from orders where shipregion is null;
-- Lecture 35: Exercises
-- AdventureWorks database for Lecture 35
-- Return the name, weight, and productnumber of all the products ordered by weight from lightest to heaviest.
-- (Remember to use schema to reach table. It is in production schema.)
select
product.name,
product.weight,
product.productnumber
from production.product
order by product.weight asc;
-- Return the records from purchasing.productvendor for productid = 407 in order of averageleadtime from shortest to longest.
select * from purchasing.productvendor
where productid = 407
order by averageleadtime asc;
-- Find all the sales.salesorderdetail records for productid 799 and order them by largest orderqty to smallest.
select * from sales.salesorderdetail where productid=799 order by orderqty desc;
-- What is the largest discount percentage offered in the specialoffer table.
select discountpct from sales.specialoffer order by discountpct desc limit 1;
select max(discountpct) from sales.specialoffer;
-- Find the smallest number of sickleavehours for an employee.
select sickleavehours from humanresources.employee order by sickleavehours asc limit 1
select min(sickleavehours) from humanresources.employee
-- Find entry for the employee with the smallest sickleave hours
select * from humanresources.employee order by sickleavehours asc limit 1
-- Find the largest rejected quantity in the purchaseorderdetail table
select rejectedqty from purchasing.purchaseorderdetail order by orderqty desc limit 1
select max(rejectedqty) as max_rejected_qty from purchasing.purchaseorderdetail
-- Find the average rate from employeepayhistory table.
select avg(rate) as average_rate from humanresources.employeepayhistory;
-- Find the average standardcost in the productcosthistory table for productid 738.
select avg(standardcost) as avg_std_cost from production.productcosthistory where productid = 738;
-- Find the sum of scrappedqty from the workorder table for productid 529.
select sum(scrappedqty) as sum_scrapped_qty from production.workorder where productid = 529;
-- Find all vendor names with a name that starts with letter G.
select distinct vendor.name from purchasing.vendor where vendor.name like 'G%'
-- Find all vendor names that have the word Bike in them.
select distinct vendor.name from purchasing.vendor where vendor.name like '%Bike%';
-- Search the person table for every firstname that has t as a second letter.
select * from person.person where person.firstname like '_t%';
-- Return the first 20 records from emailaddress table
select * from person.emailaddress limit 20;
-- Return the first 2 records from productcategory table
select * from production.productcategory limit 2;
-- How many product records have a missing weight value
select count(*) from production.product where product.weight is null;
-- How many person records have an additionalcontactinfo field that has a value
select count(*) from person.person where additionalcontactinfo is not null;
-- Section 8: Joining multiple tables together
-- https://dataschool.com/how-to-teach-people-sql/full-outer-join-animated/
-- Keep in mind, we use Northwind as the database, and refer to 01-Northwind-A4-Size-for-Print.png
-- Lecture 37: Grabbing Info from Two tables
-- Do you want records that only have data on both tables (inner join)
-- e.g. only orders with order details
-- Do you want all records from first table and any records from second (Left join)
-- e.g. all customers and any orders they might have
-- Do you want all records of one table matched with all records of second table? (cross join)
-- Inner Join Syntax:
select <column1>, <column2>, ...
from table1 inner join table2
on table1.column_name = table2.column_name
-- List a table that gives customername, orderdate and shipcounty
select companyname, contactname, orderdate, shipcountry from customers inner join orders
on customers.customerid = orders.customerid
-- Connect employees to orders and pull back firstname, lastname and order date for all orders
select firstname, lastname, orderdate from employees inner join orders
on employees.employeeid = orders.employeeid;
-- connect products and suppliers and pull back companyname, unitprice and unitsinstock
select companyname, unitprice, unitsinstock from products inner join suppliers
on products.supplierid = suppliers.supplierid;
-- Lecture 38: Grabbing information from multiple tables
-- Syntax:
select <column1>, <column2>, ...
from table1 inner join table2 on table1.column_name = table2.column_name
inner join table3 on table1.column_name = table3.column_name
inner join table4 on table1.column_name = table4.column_name
...
-- Connect Customers, Orders, OrderDetails
-- Bring back companyname (Customers), orderdate (Orders),
-- productid (OrderDetails), unitprice (OrderDetails) and quantity (OrderDetails)
select companyname, orderdate, productid, unitprice, quantity
from orders inner join customers on customers.customerid = orders.customerid
inner join order_details on orders.orderid = order_details.orderid;
-- Connect products to previous query and add product name to fiels returned
select customers.companyname, orders.orderdate, order_details.productid, order_details.unitprice, order_details.quantity,
products.productname
from orders inner join customers on customers.customerid = orders.customerid
inner join order_details on orders.orderid = order_details.orderid
inner join products on products.productid = order_details.productid
-- Connect categories to previous query and add categoryname to fields returned
select customers.companyname, orders.orderdate, order_details.productid, order_details.unitprice, order_details.quantity,
products.productname, categories.categoryname
from orders inner join customers on customers.customerid = orders.customerid
inner join order_details on orders.orderid = order_details.orderid
inner join products on products.productid = order_details.productid
inner join categories on products.categoryid = categories.categoryid;
-- Take the previous query and add a WHERE clause selecting the category name of Seafood
-- and the amount spent >= 500
select customers.companyname, orders.orderdate, order_details.productid, order_details.unitprice, order_details.quantity,
products.productname, categories.categoryname
from orders inner join customers on customers.customerid = orders.customerid
inner join order_details on orders.orderid = order_details.orderid
inner join products on products.productid = order_details.productid
inner join categories on products.categoryid = categories.categoryid
where categories.categoryname = 'Seafood' and order_details.unitprice * order_details.quantity >= 500;
select companyname, orderdate, productid, productname, order_details.unitprice, quantity
from orders inner join customers using(customerid)
inner join order_details using(orderid)
inner join products using(productid)
inner join categories using(categoryid)
where categoryname = 'Seafood' and (order_details.unitprice * order_details.quantity) >= 500
-- Lecture 39: Left Joins
-- Pulls back all records in the first table and any matching records in the second table
-- Syntax:
select <column1>, <column2>, ...
from table1 left join table2 on table1.column_name = table2.column_name
-- Connect Customers table to Orders Table
-- Bring back company name and order id
select companyname, orderid from customers left join orders on customers.customerid = orders.customerid;
-- Take the previous query and look for customers without orders
select companyname from customers left join orders on customers.customerid = orders.customerid
where orderid is null;
-- Do a left join between products and order_details
select productname, orderid from products left join order_details on products.productid = order_details.productid;
-- Use the previous query and look for products without orders
select productname, orderid from products left join order_details on products.productid = order_details.productid
where orderid is null;
select * from products left join order_details using(productid)
where order_details.orderid is null;
-- Lecture 40: Right Joins
-- Pull back maching records from the first table and all records in the second table
-- Syntax:
select <column1>, <column2>, ...
from table1 right join table2 on table1.column_name = table2.column_name
-- Connect Orders to customers
-- Bring back companyname, orderid and use right join
select companyname, orderid from orders right join customers on orders.customerid = customers.customerid;
select companyname, orderid from orders right join customers using(customerid);
-- Lets look for orders without customers using right join
select orderid, customers.customerid from customers right join orders on customers.customerid = orders.customerid
where customers.customerid is null;
select orderid, orders.customerid from customers right join orders using(customerid)
where customers.customerid is null
-- Lets look for customers without orders using right join
select companyname from orders right join customers on orders.customerid = customers.customerid
where orderid is null;
select companyname from orders right join customers using(customerid)
where orders.orderid is null;
-- Do a right join between customercustomerdemo and customers
select customers.customerid, companyname, customertypeid
from customercustomerdemo right join customers on customercustomerdemo.customerid = customers.customerid;
select customers.customerid, companyname, customercustomerdemo.customertypeid
from customercustomerdemo right join customers using(customerid);
-- Lecture 41: Full joins
-- pulls all records in first table and all records in second table
-- even if there is null in one side or the other side
-- Syntax:
select <column1>, <column2>, ...
from table1 full join table2 on table1.column_name = table2.column_name
-- Documentation: https://www.postgresqltutorial.com/postgresql-full-outer-join/
-- Connect Orders to Customers via full join
-- Bring back companyname and orderid
select companyname, orderid from orders full join customers on orders.customerid = customers.customerid
select companyname, orderid from customers full join orders on orders.customerid = customers.customerid
select companyname, orderid from orders full join customers using(customerid);
-- orders without customers + customers without orders + inner join of customers & orders
-- Do a full join between products and categories
select productname, categoryname from products full join categories on products.categoryid = categories.categoryid;
select productname, categoryname from products full join categories using(categoryid);
-- Lecture 42: Self joins
-- Connect a table back to itself
-- Applicable cases:
-- Hierarchy - like employees who report to other employees
-- Looking for similarities or dissimilarities same column
-- everyone in the same city or same birthdate
-- Usage:
-- Since all the columns are the same, we must use aliases to rename the tables
-- so we can differentiate which version of table we are referring to
-- Alias A : Employees + Alias B : Employees
select column1, column2, ..
from table1 as t1 join table1 as t2 on t1.column=t2.column
where condition
-- Find customer pairs who are in the same city and order by city ascending
select c1.companyname as customer_1, c2.companyname as customer_2, c1.city as city
from customers as c1 join customers as c2 on c1.city = c2.city
where c1.customerid != c2.customerid
order by c1.city asc;
select c1.companyname as customer_1, c2.companyname as customer_2, c1.city
from customers as c1 join customers as c2 using(city)
where c1.customerid <> c2.customerid
order by c1.city asc;
select
c1.companyname as customer_1, c2.companyname as customer_2, c1.city
from customers as c1 inner join customers as c2 using(city)
where c1.customerid <> c2.customerid
order by c1.city asc;
-- Find supplier pairs from same country and order by country
select s1.companyname as supplier1, s2.companyname as supplier2, s1.country as country
from suppliers as s1 join suppliers as s2 on s1.country = s2.country
where s1.supplierid <> s2.supplierid
order by s1.country;
select
s1.companyname as supplier1, s2.companyname as supplier2, s1.country
from suppliers as s1 inner join suppliers as s2 using(country)
where s1.supplierid <> s2.supplierid
order by s1.country asc;
-- Lecture 43: using USING keyword in ON statements in joins
-- Usage:
-- on customers.customerid = orders.customerid
-- vs.
-- USING(customerid)
-- Do an inner join of order with order_details with USING
select *
from orders inner join order_details using(orderid)
-- add products to the previous join of orders and order_details
select *
from orders inner join order_details using(orderid)
inner join products using(productid)
-- Lecture 44: NATURAL JOIN
-- NATURAL is a shorthand for USING with a list of all columns
-- that are the same in both tables
-- Syntax:
from table1 natural join table2
-- equals to
from table1 inner join table2 using(column)
-- equals to
from table1 inner join table2 on table1.column = table2.column
-- join order and order_details using natural join
select * from orders natural join order_details
-- equals to
select * from orders inner join order_details using(orderid)
-- equals to
select * from orders inner join order_details on orders.orderid = order_details.orderid
-- add customers to previous query using NATURAL join
-- you must order the joins correctly;
-- The NATURAL must connect previous table to the next table or
-- it will do a cross join connecting every row to every other row
select * from customers natural join orders
natural join order_details
-- Lecture 45: Exercises
-- NOTE: Use the AdventureWorks database unless stated otherwise
-- Join (with inner join) together person, personphone, businessentity and phonenumbertype tables in the person schema.
-- Return first name, middle name, last name, phone number and the name of the phone number type (home, office, etc.)
-- Order by business entity id descending.
select person.firstname, person.middlename, person.lastname, personphone.phonenumber, phonenumbertype.name
from person.person inner join person.personphone using(businessentityid)
inner join person.businessentity using(businessentityid)
inner join person.phonenumbertype using(phonenumbertypeid)
order by person.businessentityid desc;
-- Join (Inner) productmodel, productmodelproductiondescriptionculture, productdescription and culture from the production schema.
-- Return the productmodel name, culture name, and productdescription description ordered by the product model name in ascending order.
select pm.name, pc.name, description
from production.productmodel as pm inner join production.productmodelproductdescriptionculture using(productmodelid)
inner join production.productdescription using(productdescriptionid)
inner join production.culture as pc using(cultureid)
order by pm.name asc;
-- Add a join to previous example to production.product and return the product name field in addition to other information.
select
product.name,
productmodel.name,
culture.name,
productdescription.description
from production.productmodel
inner join production.product using(productmodelid)
inner join production.productmodelproductdescriptionculture using(productmodelid)
inner join production.productdescription using(productdescriptionid)
inner join production.culture using(cultureid)
order by productmodel.name asc;
-- Join product and productreview in the schema table. Include every record from product and any reviews they have.
-- Return the product name, review rating and comments. Order by rating in ascending order.
select product.name,
productreview.rating,
productreview.comments
from production.product left join production.productreview using(productid)
order by productreview.rating asc;
-- Use a right join to combine workorder and product from production schema to bring back all products and any work orders they have.
-- Include the product name and workorder orderqty and scrappedqty fields. Order by productid ascending
select
product.name,
workorder.orderqty,
workorder.scrappedqty
from production.workorder right join production.product using(productid)
order by product.productid asc;
-- Section 9: Grouping and Aggregation
-- Lecture 46: GROUP BY
-- NOTE: Use the Northwind database unless stated otherwise
-- How many customers do we have in each county? ordered by # of customers in each country in descending order
select country, count(*) as num_of_customers
from customers group by country
order by num_of_customers desc;
-- You can use GROUP BY with joins
-- What is the # of products for each category? ordered by # of products in desc order
-- Teachers solution:
SELECT COUNT(*),categoryname
FROM categories
JOIN products ON categories.categoryid=products.categoryid
GROUP BY categoryname
ORDER BY COUNT(*) DESC;
-- in the previous solution, we grouped by category name, but ideally we should group by categoryid
-- we might also take into account categories without products
-- we might also take into account products without categories
select categories.categoryid,
categories.categoryname,
case
when sum(productid) is null then 0
else count(*)
end as num_of_products
from categories full join products using(categoryid)
group by categories.categoryid
order by num_of_products desc;
-- What is the total # of products sold for each category?
-- ordered by total # of products sold in desc order
select
categories.categoryid,
categories.categoryname,
sum(od.quantity) as total_num_of_products_sold
from products inner join order_details as od using(productid)
inner join categories using(categoryid)
group by categories.categoryid
order by total_num_of_products_sold desc;
-- if we had product categories that does not yet have products
-- or if we had certain products that do not yet have order details then this solution would be better:
select
categories.categoryid,
categories.categoryname,
case
when sum(products.productid) is null then 0
when sum(order_details.orderid) is null then 0
else sum(order_details.quantity)
end as total_num_of_products_sold
from categories
left join products using(categoryid)
left join order_details using(productid)
group by categories.categoryid
order by total_num_of_products_sold desc;
-- What is the average number of items ordered for products ordered by the average number of items
-- in descending order
-- close to teacher's solution:
select productname, avg(quantity) as avg_num_of_items_ordered
from products inner join order_details using(productid)
group by products.productid
order by avg_num_of_items_ordered desc
-- we used inner join to select products with order details and vice versa.
-- what if we have products with no order details? To take them into account:
select
products.productname,
case
when sum(order_details.orderid) is null then 0
else avg(quantity)
end as avg_num_products_ordered
from products left join order_details using(productid)
group by products.productid
order by avg_num_products_ordered desc;
-- What is the average number of items ordered for all the products ordered by the average amount in descending order
-- if a product does not have any orders, then the average amount should be 0
select productname, COALESCE(avg(quantity),0) as avg_num_products_ordered
from products left join order_details using(productid)
group by products.productid
order by avg_num_products_ordered desc;
-- Reference: https://www.postgresqltutorial.com/postgresql-coalesce/
-- coalesce : unite
select
products.productname,
case
when avg(quantity) is null then 0
else avg(quantity)
end as avg_num_products_ordered
from products left join order_details using(productid)
group by products.productid
order by avg_num_products_ordered desc;
-- How many suppliers do we have in each country? order it by # of suppliers desc
select country, count(*) as number_of_suppliers
from suppliers group by country
order by number_of_suppliers desc;
-- Total value of each product sold for year 1997 ordered by total value in descending form
-- Teachers solution: Note that we can use WHERE before GROUP BY
select
productname,
sum((od.unitprice*od.quantity)-od.discount) as total_sold
from products inner join order_details as od using(productid)
inner join orders using(orderid)
where extract(year from orderdate) = 1997
group by products.productid
order by total_sold desc;
-- OR:
select
products.productname,
sum((order_details.unitprice*order_details.quantity)-order_details.discount) as total_value
from products
inner join order_details using(productid)
inner join orders using(orderid)
group by productid, extract(year from orderdate)
having extract(year from orderdate) = 1997
order by total_value desc;
-- Lecture 47: Use HAVING to filter groups
-- Syntax:
Select column_names
from table1
where condition
group by column_name(s),
having condition
order by column_names
-- WHERE filters records before grouping
-- HAVING filters records after grouping
-- Find all products that sold less than 2000$ order by amount sold asc
select
products.productid,
products.productname,
coalesce(sum((od.unitprice*od.quantity)-od.discount), 0) as amount_sold
from products left join order_details as od using(productid)
group by productid
having coalesce(sum((od.unitprice*od.quantity)-od.discount), 0) < 2000
order by amount_sold asc;
-- coalesce (postgresql) ?= ifnull (mysql)
-- List customers that have bought more than 5000$ of products in descending order
select
customers.customerid,
customers.companyname,
sum((od.unitprice*od.quantity)-od.discount) as total_amount_bought
from customers
inner join orders using(customerid)
inner join order_details as od using(orderid)
group by customers.customerid
having sum((od.unitprice*od.quantity)-od.discount) > 5000
order by total_amount_bought desc;
-- List customers that have bought more than 5000$ of products in descending order
-- with order date in first six months of the year 1997
select column_name, data_type, character_maximum_length, column_default, is_nullable
from INFORMATION_SCHEMA.COLUMNS where table_name = 'orders';
select
customers.customerid,
customers.companyname,
sum((od.unitprice * od.quantity) - od.discount) as total_purchase
from customers
inner join orders using(customerid)
inner join order_details as od using(orderid)
where orderdate between date('Jan-1-1997') and date('June-30-1997')
group by customers.customerid
having sum((od.unitprice * od.quantity) - od.discount) > 5000
order by total_purchase desc;
-- Lecture 48 : Grouping Sets
-- What is the term "Grouping Set" ?
-- Any group of columns you are using in GROUP BY phrase
-- You already have been using this. For ex:
-- Grouping set = country
select count(*), country
from customers
group by country
order by count(*) desc
-- Before proceeding, read this tutorial & use practice_db
-- https://www.postgresqltutorial.com/postgresql-grouping-sets/ (1)
-- The GROUPING SETS allows you to define multiple grouping sets in the same query.
-- The general syntax of the GROUPING SETS is as follows:
SELECT
c1,
c2,
aggregate_function(c3)
FROM
table_name
GROUP BY
GROUPING SETS (
(c1, c2),
(c1),
(c2),
()
);
-- Use case: Referring to sales table in practice_db mentioned in (1), if we want to have an aggragate table
-- containing the following grouping sets:
-- the number of products sold for all brands and segments
-- the number of products sold by segment
-- the number of products sold by a brand
-- the number of products sold by brand and segment together
-- What if we wanted to do more than one column in a grouping set?
-- Then we can UNION ALL them together
-- We need to write more than one query : multiple passes through data : much slower
-- Proper way:
group by grouping sets ((field1), (field2), (field3, field4))
-- Total sales grouped by category and then the product & category together
-- ordered by categoryname & productname in ascending order
select
categories.categoryname,
products.productname,
sum((od.quantity*od.unitprice)-od.discount) as total_sales
from categories
inner join products using(categoryid)
inner join order_details as od using(productid)
group by grouping sets(
(categories.categoryname),
(products.productname, categories.categoryname)
)
order by categories.categoryname, products.productname;
-- OR;
select
categories.categoryname as category,
products.productname as product,
sum((od.unitprice*od.quantity)-od.discount) as total_sales
from products inner join order_details as od using(productid)