├── pcs.png ├── README.md └── SQLslides.ipynb /pcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caocscar/intro-to-SQL/master/pcs.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # intro-to-SQL 2 | 3 | This is an iPython Notebook slides presentation to provide a basic introduction to SQL. The slides are best viewed here: http://nbviewer.jupyter.org/format/slides/github/margamo/intro-to-SQL/blob/master/SQLslides.ipynb#/ 4 | -------------------------------------------------------------------------------- /SQLslides.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": false, 8 | "slideshow": { 9 | "slide_type": "skip" 10 | } 11 | }, 12 | "outputs": [ 13 | { 14 | "name": "stdout", 15 | "output_type": "stream", 16 | "text": [ 17 | "Populating the interactive namespace from numpy and matplotlib\n" 18 | ] 19 | } 20 | ], 21 | "source": [ 22 | "%pylab inline" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": { 28 | "slideshow": { 29 | "slide_type": "slide" 30 | } 31 | }, 32 | "source": [ 33 | " \n", 34 | " \n", 35 | "# Introduction to SQL\n", 36 | "\n", 37 | "By Maggie Orton and Alex Cao \n", 38 | "\n", 39 | "\n", 40 | "March 14, 2017 \n", 41 | "\n", 42 | "CSCAR at The University of Michigan" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": { 48 | "slideshow": { 49 | "slide_type": "fragment" 50 | } 51 | }, 52 | "source": [ 53 | "Please fill out the workshop sign-in here\n" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": { 59 | "slideshow": { 60 | "slide_type": "fragment" 61 | } 62 | }, 63 | "source": [ 64 | "We'll practice SQL using the W3Schools online database here" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": { 70 | "slideshow": { 71 | "slide_type": "fragment" 72 | } 73 | }, 74 | "source": [ 75 | "Structured Query Language (\"SQL\") allows you to extract or change specific information in a relational database (i.e. a series of tables). " 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": { 81 | "slideshow": { 82 | "slide_type": "fragment" 83 | } 84 | }, 85 | "source": [ 86 | " MySQL, SQLite, PostgreSQL, SQL Server, etc. are all database management systems that rely on SQL. Each has its own special variety of SQL, but the general format of the queries is the same. " 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": { 92 | "slideshow": { 93 | "slide_type": "slide" 94 | } 95 | }, 96 | "source": [ 97 | "# SQL Queries\n", 98 | "\n", 99 | "## Format\n", 100 | "Series of commands followed by argument(s)\n", 101 | "\n", 102 | "When dealing with multiple tables, identify a column name with tablename.columnname\n", 103 | "\n", 104 | "End query with semicolon for multiple consecutive queries\n", 105 | "\n", 106 | "## Style + Readability\n", 107 | "Commands in all-caps\n", 108 | "\n", 109 | "Each command set on new line\n", 110 | "\n", 111 | "## Comments\n", 112 | "Single-line comments:\n", 113 | "\n", 114 | "-- begin line with two hyphens\n", 115 | "\n", 116 | "Multi-line comments:\n", 117 | "\n", 118 | "/\\* enclose comment\n", 119 | "in asterisk|slashes \\*/" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": { 125 | "slideshow": { 126 | "slide_type": "slide" 127 | } 128 | }, 129 | "source": [ 130 | "# SELECT, FROM, AS\n", 131 | "The SELECT command specifies the desired columns \n", 132 | "\n", 133 | "The FROM command specifies the table from which those columns should be selected\n", 134 | "\n", 135 | "The AS command temporarily renames a column or table with the specified name (an \"alias\")\n", 136 | "\n", 137 | "An '\\*' character selects all columns in a table" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": { 143 | "slideshow": { 144 | "slide_type": "fragment" 145 | } 146 | }, 147 | "source": [ 148 | "## Example\n", 149 | "The 'Employees' table contains the columns:\n", 150 | "\n", 151 | " EmployeeID, LastName, FirstName, BirthDate, Photo, Notes" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": { 157 | "slideshow": { 158 | "slide_type": "fragment" 159 | } 160 | }, 161 | "source": [ 162 | "To retrieve all columns from this table, you would use the command \n", 163 | "\n", 164 | " SELECT * \n", 165 | " FROM Employees" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": { 171 | "slideshow": { 172 | "slide_type": "fragment" 173 | } 174 | }, 175 | "source": [ 176 | "To retrieve only the name-related columns from this table, you would use the command\n", 177 | "\n", 178 | " SELECT LastName, FirstName \n", 179 | " FROM Employees" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": { 185 | "slideshow": { 186 | "slide_type": "fragment" 187 | } 188 | }, 189 | "source": [ 190 | "To do the above while renaming the columns as \"last\" and \"first\":\n", 191 | "\n", 192 | " SELECT LastName AS Last, FirstName AS First \n", 193 | " FROM Employees" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": { 199 | "slideshow": { 200 | "slide_type": "subslide" 201 | } 202 | }, 203 | "source": [ 204 | "## Practice\n", 205 | "1\\. Retrieve the Products table" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": { 211 | "slideshow": { 212 | "slide_type": "fragment" 213 | } 214 | }, 215 | "source": [ 216 | "2\\. Retrieve only the product names and prices from Products" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": { 222 | "slideshow": { 223 | "slide_type": "fragment" 224 | } 225 | }, 226 | "source": [ 227 | "3\\. Retrieve the product names and prices from Products, but call them PN and Dollars" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": { 233 | "slideshow": { 234 | "slide_type": "notes" 235 | } 236 | }, 237 | "source": [ 238 | "### Answers\n", 239 | "1. SELECT * FROM Products (77)\n", 240 | "2. SELECT ProductName, Price FROM Products (77)\n", 241 | "3. SELECT ProductName AS 'PN', Price AS 'Dollars' FROM Products (77)" 242 | ] 243 | }, 244 | { 245 | "cell_type": "markdown", 246 | "metadata": { 247 | "collapsed": true, 248 | "slideshow": { 249 | "slide_type": "slide" 250 | } 251 | }, 252 | "source": [ 253 | "# COUNT\n", 254 | "COUNT returns the number of non-null results in the specified column or the number of non-null rows. " 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": { 260 | "slideshow": { 261 | "slide_type": "fragment" 262 | } 263 | }, 264 | "source": [ 265 | "## Example\n", 266 | "To count the number of non-null rows in the Employees table:\n", 267 | "\n", 268 | " SELECT COUNT(*) \n", 269 | " FROM Employees" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": { 275 | "slideshow": { 276 | "slide_type": "subslide" 277 | } 278 | }, 279 | "source": [ 280 | "## Practice\n", 281 | "Count the number of Orders in the Orders table" 282 | ] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "metadata": { 287 | "slideshow": { 288 | "slide_type": "notes" 289 | } 290 | }, 291 | "source": [ 292 | "### Answers\n", 293 | "SELECT COUNT(OrderID) FROM Orders" 294 | ] 295 | }, 296 | { 297 | "cell_type": "markdown", 298 | "metadata": { 299 | "collapsed": true, 300 | "slideshow": { 301 | "slide_type": "slide" 302 | } 303 | }, 304 | "source": [ 305 | "# WHERE, AND, OR\n", 306 | "The WHERE command retrieves rows that satisfy a given condition\n", 307 | "\n", 308 | "Simple conditions:\n", 309 | "- = Equals \n", 310 | "- != or <> Does not equal\n", 311 | "- \\> or < Is greater/less than\n", 312 | "- \\>= or <= Is greater/less than or equal to\n", 313 | "\n", 314 | "Additional conditions covered in following slides:\n", 315 | "- a AND b\n", 316 | "- a OR b\n", 317 | "- BETWEEN a AND b\n", 318 | "- IN ('a','b','c')\n", 319 | "- LIKE 'a'\n", 320 | "\n", 321 | "BETWEEN, IN, and LIKE can all be modified using the \"NOT\" keyword to retrieve rows that are not a match\n", 322 | " " 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": { 328 | "slideshow": { 329 | "slide_type": "fragment" 330 | } 331 | }, 332 | "source": [ 333 | "## Example\n", 334 | "Using the 'Employees' table again, suppose you want to retrieve all employee information for those born before 1960:\n", 335 | " \n", 336 | " SELECT * \n", 337 | " FROM Employees \n", 338 | " WHERE BirthDate < '1960-01-01'" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "metadata": { 344 | "slideshow": { 345 | "slide_type": "fragment" 346 | } 347 | }, 348 | "source": [ 349 | "Filtering out everyone whose last name is King:\n", 350 | " \n", 351 | " SELECT * \n", 352 | " FROM Employees \n", 353 | " WHERE LastName != 'King'" 354 | ] 355 | }, 356 | { 357 | "cell_type": "markdown", 358 | "metadata": { 359 | "slideshow": { 360 | "slide_type": "fragment" 361 | } 362 | }, 363 | "source": [ 364 | "Applying both filters: \n", 365 | "\n", 366 | " SELECT * \n", 367 | " FROM Employees \n", 368 | " WHERE Lastname != 'King' AND BirthDate < '1960-01-01'" 369 | ] 370 | }, 371 | { 372 | "cell_type": "markdown", 373 | "metadata": { 374 | "slideshow": { 375 | "slide_type": "fragment" 376 | } 377 | }, 378 | "source": [ 379 | "Applying either filter:\n", 380 | "\n", 381 | " SELECT * \n", 382 | " FROM Employees \n", 383 | " WHERE Lastname != 'King' OR BirthDate < '1960-01-01'" 384 | ] 385 | }, 386 | { 387 | "cell_type": "markdown", 388 | "metadata": { 389 | "slideshow": { 390 | "slide_type": "subslide" 391 | } 392 | }, 393 | "source": [ 394 | "## Practice\n", 395 | "1\\. Retrieve orders starting in 1997" 396 | ] 397 | }, 398 | { 399 | "cell_type": "markdown", 400 | "metadata": { 401 | "slideshow": { 402 | "slide_type": "fragment" 403 | } 404 | }, 405 | "source": [ 406 | "2\\. Retrieve orders starting in 1997 and with shipper IDs of at least 2" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": { 412 | "slideshow": { 413 | "slide_type": "fragment" 414 | } 415 | }, 416 | "source": [ 417 | "3\\. Retrieve orders starting in 1997 or with shipper IDs of at least 2" 418 | ] 419 | }, 420 | { 421 | "cell_type": "markdown", 422 | "metadata": { 423 | "slideshow": { 424 | "slide_type": "notes" 425 | } 426 | }, 427 | "source": [ 428 | "### Answers\n", 429 | "1. SELECT * FROM Orders WHERE OrderDate >= '1997-01-01'\n", 430 | "2. SELECT * FROM Orders WHERE OrderDate >= '1997-01-01' AND ShipperID > 1\n", 431 | "3. SELECT * FROM Orders WHERE OrderDate >= '1997-01-01' OR ShipperID > 1" 432 | ] 433 | }, 434 | { 435 | "cell_type": "markdown", 436 | "metadata": { 437 | "collapsed": true, 438 | "slideshow": { 439 | "slide_type": "slide" 440 | } 441 | }, 442 | "source": [ 443 | "# BETWEEN\n", 444 | "\n", 445 | "The BETWEEN command gives a range of values (inclusive)\n", 446 | "\n", 447 | "BETWEEN can be modified using the \"NOT\" keyword to retrieve rows that are not a match" 448 | ] 449 | }, 450 | { 451 | "cell_type": "markdown", 452 | "metadata": { 453 | "slideshow": { 454 | "slide_type": "fragment" 455 | } 456 | }, 457 | "source": [ 458 | "## Example\n", 459 | "To retrieve orders placed in January of 1997:\n", 460 | " \n", 461 | " SELECT * \n", 462 | " FROM Orders \n", 463 | " WHERE OrderDate \n", 464 | " BETWEEN '1997-01-01' AND '1997-01-31'" 465 | ] 466 | }, 467 | { 468 | "cell_type": "markdown", 469 | "metadata": { 470 | "slideshow": { 471 | "slide_type": "subslide" 472 | } 473 | }, 474 | "source": [ 475 | "## Practice\n", 476 | "Retrieve the Product ID and Quantity from the OrderDetails table for Order IDs between 10250 and 10350 (inclusive)" 477 | ] 478 | }, 479 | { 480 | "cell_type": "markdown", 481 | "metadata": { 482 | "slideshow": { 483 | "slide_type": "notes" 484 | } 485 | }, 486 | "source": [ 487 | "### Answers\n", 488 | "SELECT ProductID, Quantity FROM OrderDetails WHERE OrderID BETWEEN 10250 AND 10350 (269)" 489 | ] 490 | }, 491 | { 492 | "cell_type": "markdown", 493 | "metadata": { 494 | "collapsed": true, 495 | "slideshow": { 496 | "slide_type": "slide" 497 | } 498 | }, 499 | "source": [ 500 | "# IN\n", 501 | "The IN command gives multiple possible matching values" 502 | ] 503 | }, 504 | { 505 | "cell_type": "markdown", 506 | "metadata": { 507 | "slideshow": { 508 | "slide_type": "fragment" 509 | } 510 | }, 511 | "source": [ 512 | "## Example\n", 513 | "\n", 514 | "Retrieving Employee IDs for employees not named Nancy or Andrew:\n", 515 | "\n", 516 | " SELECT EmployeeID FROM Employees WHERE FirstName NOT IN ('Nancy', 'Andrew') " 517 | ] 518 | }, 519 | { 520 | "cell_type": "markdown", 521 | "metadata": { 522 | "slideshow": { 523 | "slide_type": "subslide" 524 | } 525 | }, 526 | "source": [ 527 | "## Practice\n", 528 | "Return the names of customers in Mexico or the US" 529 | ] 530 | }, 531 | { 532 | "cell_type": "markdown", 533 | "metadata": { 534 | "slideshow": { 535 | "slide_type": "notes" 536 | } 537 | }, 538 | "source": [ 539 | "### Answers\n" 540 | ] 541 | }, 542 | { 543 | "cell_type": "markdown", 544 | "metadata": { 545 | "slideshow": { 546 | "slide_type": "slide" 547 | } 548 | }, 549 | "source": [ 550 | "# LIKE, wildcards\n", 551 | "The LIKE command specifies a pattern to match, such as 'Nancy' or '1999'. \n", 552 | "\n", 553 | "Wildcards are characters that stand in for a range of possible values. \n", 554 | "\n", 555 | "Wildcards:\n", 556 | " \n", 557 | " % A string of 0+ characters\n", 558 | " \n", 559 | " _ A single character\n", 560 | " \n", 561 | " [...] A single character from the range or list in the brackets\n", 562 | " \n", 563 | " [^...] A single character not from the range or list in the brackets\n", 564 | "\n", 565 | "Without any wildcards, LIKE will match only values equal to the exact pattern." 566 | ] 567 | }, 568 | { 569 | "cell_type": "markdown", 570 | "metadata": { 571 | "slideshow": { 572 | "slide_type": "fragment" 573 | } 574 | }, 575 | "source": [ 576 | "## Example\n", 577 | "To match all customers with names starting with M, we use the query\n", 578 | "\n", 579 | " SELECT * FROM Customers \n", 580 | " WHERE CustomerName Like 'M%'" 581 | ] 582 | }, 583 | { 584 | "cell_type": "markdown", 585 | "metadata": { 586 | "slideshow": { 587 | "slide_type": "fragment" 588 | } 589 | }, 590 | "source": [ 591 | "To match all customers with names starting with letters after D, we can use the query\n", 592 | "\n", 593 | " SELECT * FROM Customers \n", 594 | " WHERE CustomerName Like '[^a-d]%'" 595 | ] 596 | }, 597 | { 598 | "cell_type": "markdown", 599 | "metadata": { 600 | "slideshow": { 601 | "slide_type": "subslide" 602 | } 603 | }, 604 | "source": [ 605 | "## Practice\n", 606 | "1\\. Retrieve all information about customers from two- or three-letter named countries" 607 | ] 608 | }, 609 | { 610 | "cell_type": "markdown", 611 | "metadata": { 612 | "slideshow": { 613 | "slide_type": "fragment" 614 | } 615 | }, 616 | "source": [ 617 | "2\\. Retrieve the customer names from people whose contacts have a last name starting with S" 618 | ] 619 | }, 620 | { 621 | "cell_type": "markdown", 622 | "metadata": { 623 | "slideshow": { 624 | "slide_type": "notes" 625 | } 626 | }, 627 | "source": [ 628 | "### Answers\n", 629 | "1. SELECT * FROM Customers WHERE Country LIKE '___' OR Country LIKE '__' \\(13)\n", 630 | "2. SELECT CustomerName FROM Customers WHERE ContactName LIKE '% S%' (7)" 631 | ] 632 | }, 633 | { 634 | "cell_type": "markdown", 635 | "metadata": { 636 | "slideshow": { 637 | "slide_type": "slide" 638 | } 639 | }, 640 | "source": [ 641 | "# DISTINCT\n", 642 | "The DISTINCT command retrieves only distinct combinations of the specified columns.\n", 643 | "\n", 644 | "It is also commonly used in combination with COUNT to return the number of distinct combinations." 645 | ] 646 | }, 647 | { 648 | "cell_type": "markdown", 649 | "metadata": { 650 | "slideshow": { 651 | "slide_type": "fragment" 652 | } 653 | }, 654 | "source": [ 655 | "## Example\n", 656 | "To retrieve a list of all CustomerIDs with orders from the Orders table:\n", 657 | "\n", 658 | " SELECT DISTINCT CustomerID FROM Orders" 659 | ] 660 | }, 661 | { 662 | "cell_type": "markdown", 663 | "metadata": { 664 | "slideshow": { 665 | "slide_type": "fragment" 666 | } 667 | }, 668 | "source": [ 669 | "To retrieve all past combinations of employee IDs and shipper IDs:\n", 670 | " \n", 671 | " SELECT DISTINCT EmployeeID, ShipperID FROM Orders" 672 | ] 673 | }, 674 | { 675 | "cell_type": "markdown", 676 | "metadata": { 677 | "slideshow": { 678 | "slide_type": "fragment" 679 | } 680 | }, 681 | "source": [ 682 | "To count the distinct combinations of employee IDs and shipper IDs:\n", 683 | "\n", 684 | " SELECT COUNT(DISTINCT EmployeeID, ShipperID) FROM Orders" 685 | ] 686 | }, 687 | { 688 | "cell_type": "markdown", 689 | "metadata": { 690 | "slideshow": { 691 | "slide_type": "subslide" 692 | } 693 | }, 694 | "source": [ 695 | "## Practice\n", 696 | "1\\. Retrieve all distinct combinations of ProductID and Quantity from the OrderDetails table" 697 | ] 698 | }, 699 | { 700 | "cell_type": "markdown", 701 | "metadata": { 702 | "slideshow": { 703 | "slide_type": "fragment" 704 | } 705 | }, 706 | "source": [ 707 | "2\\. Return the number of results for question 1 " 708 | ] 709 | }, 710 | { 711 | "cell_type": "markdown", 712 | "metadata": { 713 | "slideshow": { 714 | "slide_type": "notes" 715 | } 716 | }, 717 | "source": [ 718 | "### Answers\n", 719 | "1. SELECT DISTINCT ProductID, Quantity FROM OrderDetails\n", 720 | "2. SELECT COUNT(DISTINCT ProductID, Quantity) FROM OrderDetails" 721 | ] 722 | }, 723 | { 724 | "cell_type": "markdown", 725 | "metadata": { 726 | "collapsed": true, 727 | "slideshow": { 728 | "slide_type": "slide" 729 | } 730 | }, 731 | "source": [ 732 | "# ORDER BY\n", 733 | "ORDER BY sorts the results according to the specified columns. Default is ascending, but you can use ASC/DESC to specify the ordering." 734 | ] 735 | }, 736 | { 737 | "cell_type": "markdown", 738 | "metadata": { 739 | "slideshow": { 740 | "slide_type": "fragment" 741 | } 742 | }, 743 | "source": [ 744 | "## Example\n", 745 | "To retrieve products ordered by price:\n", 746 | "\n", 747 | " SELECT ProductName, Price FROM Products ORDER BY Price DESC" 748 | ] 749 | }, 750 | { 751 | "cell_type": "markdown", 752 | "metadata": { 753 | "slideshow": { 754 | "slide_type": "subslide" 755 | } 756 | }, 757 | "source": [ 758 | "## Practice\n", 759 | "Order the customers by city and then by country, both ascending" 760 | ] 761 | }, 762 | { 763 | "cell_type": "markdown", 764 | "metadata": { 765 | "slideshow": { 766 | "slide_type": "notes" 767 | } 768 | }, 769 | "source": [ 770 | "### Answers\n", 771 | "SELECT * FROM Customers ORDER BY City ASC, Country ASC" 772 | ] 773 | }, 774 | { 775 | "cell_type": "markdown", 776 | "metadata": { 777 | "collapsed": true, 778 | "slideshow": { 779 | "slide_type": "slide" 780 | } 781 | }, 782 | "source": [ 783 | "# TOP, LIMIT\n", 784 | "TOP and LIMIT (syntax depends on type of database) retrieve only the first x results or percent of results; good for checking results before requesting a very large query or in combination with the ORDER BY command.\n", 785 | "\n", 786 | "LIMIT is only supported in MySQL and Oracle databases. " 787 | ] 788 | }, 789 | { 790 | "cell_type": "markdown", 791 | "metadata": { 792 | "slideshow": { 793 | "slide_type": "fragment" 794 | } 795 | }, 796 | "source": [ 797 | "## Example\n", 798 | "To retrieve the first three rows of customers:\n", 799 | " \n", 800 | " SELECT TOP 3 * FROM Customers" 801 | ] 802 | }, 803 | { 804 | "cell_type": "markdown", 805 | "metadata": { 806 | "slideshow": { 807 | "slide_type": "fragment" 808 | } 809 | }, 810 | "source": [ 811 | "To retrieve the ten most expensive products:\n", 812 | "\n", 813 | " SELECT TOP 10 ProductName, Price FROM Products ORDER BY Price DESC" 814 | ] 815 | }, 816 | { 817 | "cell_type": "markdown", 818 | "metadata": { 819 | "slideshow": { 820 | "slide_type": "fragment" 821 | } 822 | }, 823 | "source": [ 824 | "To retrieve the top ten percent of products by price:\n", 825 | "\n", 826 | " SELECT TOP 10 PERCENT ProductName, Price FROM Products ORDER BY Price DESC" 827 | ] 828 | }, 829 | { 830 | "cell_type": "markdown", 831 | "metadata": { 832 | "slideshow": { 833 | "slide_type": "fragment" 834 | } 835 | }, 836 | "source": [ 837 | "In MySQL or Oracle, the command would look like this:\n", 838 | "\n", 839 | " SELECT column(s)\n", 840 | " FROM table\n", 841 | " LIMIT number;" 842 | ] 843 | }, 844 | { 845 | "cell_type": "markdown", 846 | "metadata": { 847 | "slideshow": { 848 | "slide_type": "subslide" 849 | } 850 | }, 851 | "source": [ 852 | "## Practice\n", 853 | "1\\. Return the names of the oldest 50% of employees" 854 | ] 855 | }, 856 | { 857 | "cell_type": "markdown", 858 | "metadata": { 859 | "slideshow": { 860 | "slide_type": "fragment" 861 | } 862 | }, 863 | "source": [ 864 | "2\\. Return the top 10 results for products sorted by supplier ID (ascending) then product name (ascending)" 865 | ] 866 | }, 867 | { 868 | "cell_type": "markdown", 869 | "metadata": { 870 | "slideshow": { 871 | "slide_type": "notes" 872 | } 873 | }, 874 | "source": [ 875 | "### Answers\n", 876 | "1. SELECT TOP 50 PERCENT LastName, FirstName FROM Employees ORDER BY BirthDate\n", 877 | "2. SELECT TOP 10 * FROM Products ORDER BY SupplierID ASC, ProductName DESC" 878 | ] 879 | }, 880 | { 881 | "cell_type": "markdown", 882 | "metadata": { 883 | "slideshow": { 884 | "slide_type": "slide" 885 | } 886 | }, 887 | "source": [ 888 | "# JOIN\n", 889 | "JOIN connects two tables where the specified columns match.\n", 890 | "\n", 891 | "\n", 892 | "INNER JOIN - all rows where specified columns match (default)\n", 893 | "\n", 894 | "LEFT JOIN - all rows from left table and matching rows in right table\n", 895 | "\n", 896 | "RIGHT JOIN - all rows from right table and matching rows in left table\n", 897 | "\n", 898 | "FULL OUTER JOIN - all rows from left and right table\n", 899 | "\n", 900 | "\n", 901 | "Image excerpt from Pandas Cheat Sheet" 902 | ] 903 | }, 904 | { 905 | "cell_type": "markdown", 906 | "metadata": { 907 | "slideshow": { 908 | "slide_type": "fragment" 909 | } 910 | }, 911 | "source": [ 912 | "## Example\n", 913 | "To retrieve all past combinations of customer names and employee IDs:\n", 914 | "\n", 915 | " SELECT CustomerName, EmployeeID, Orders.OrderID FROM Orders\n", 916 | " JOIN Customers\n", 917 | " ON Customers.CustomerID=Orders.CustomerID" 918 | ] 919 | }, 920 | { 921 | "cell_type": "markdown", 922 | "metadata": { 923 | "slideshow": { 924 | "slide_type": "fragment" 925 | } 926 | }, 927 | "source": [ 928 | "To retrieve all past combinations of customer names and employee last names:\n", 929 | "\n", 930 | " SELECT CustomerName, LastName, Orders.OrderID FROM Orders\n", 931 | " JOIN Employees\n", 932 | " ON Employees.EmployeeID=Orders.EmployeeID\n", 933 | " JOIN Customers\n", 934 | " ON Customers.CustomerID=Orders.CustomerID" 935 | ] 936 | }, 937 | { 938 | "cell_type": "markdown", 939 | "metadata": { 940 | "slideshow": { 941 | "slide_type": "subslide" 942 | } 943 | }, 944 | "source": [ 945 | "## Practice\n", 946 | "Return the Products table with a column for the Supplier Name included" 947 | ] 948 | }, 949 | { 950 | "cell_type": "markdown", 951 | "metadata": { 952 | "slideshow": { 953 | "slide_type": "notes" 954 | } 955 | }, 956 | "source": [ 957 | "### Answers" 958 | ] 959 | }, 960 | { 961 | "cell_type": "markdown", 962 | "metadata": { 963 | "slideshow": { 964 | "slide_type": "slide" 965 | } 966 | }, 967 | "source": [ 968 | "# GROUP BY\n", 969 | "GROUP BY groups the rows according to their values in the selected column and then uses an \"aggregate function\" to create a new column with information about each group (of rows). \n", 970 | "\n", 971 | "Example aggregate functions:\n", 972 | "- COUNT()\n", 973 | "- SUM()\n", 974 | "- MAX()\n", 975 | "- MIN()\n", 976 | "- AVG()" 977 | ] 978 | }, 979 | { 980 | "cell_type": "markdown", 981 | "metadata": { 982 | "slideshow": { 983 | "slide_type": "fragment" 984 | } 985 | }, 986 | "source": [ 987 | "## Example\n", 988 | "To retrieve the total number of each product ordered:\n", 989 | " \n", 990 | " SELECT ProductID, SUM(Quantity) \n", 991 | " FROM OrderDetails\n", 992 | " GROUP BY ProductID" 993 | ] 994 | }, 995 | { 996 | "cell_type": "markdown", 997 | "metadata": { 998 | "slideshow": { 999 | "slide_type": "subslide" 1000 | } 1001 | }, 1002 | "source": [ 1003 | "## Practice\n", 1004 | "Retrieve the total number of orders in the Orders table for each Employee" 1005 | ] 1006 | }, 1007 | { 1008 | "cell_type": "markdown", 1009 | "metadata": { 1010 | "slideshow": { 1011 | "slide_type": "notes" 1012 | } 1013 | }, 1014 | "source": [ 1015 | "### Answers\n", 1016 | "SELECT EmployeeID, COUNT(*) FROM Orders\n", 1017 | "GROUP BY EmployeeID" 1018 | ] 1019 | }, 1020 | { 1021 | "cell_type": "markdown", 1022 | "metadata": { 1023 | "slideshow": { 1024 | "slide_type": "slide" 1025 | } 1026 | }, 1027 | "source": [ 1028 | "# HAVING\n", 1029 | "The HAVING command acts like a WHERE command for GROUP BY" 1030 | ] 1031 | }, 1032 | { 1033 | "cell_type": "markdown", 1034 | "metadata": { 1035 | "slideshow": { 1036 | "slide_type": "fragment" 1037 | } 1038 | }, 1039 | "source": [ 1040 | "## Example\n", 1041 | "To retrieve employees with more than fifteen orders in the Orders table:\n", 1042 | " \n", 1043 | " SELECT EmployeeID, COUNT(*) \n", 1044 | " FROM ORDERS\n", 1045 | " GROUP BY EmployeeID\n", 1046 | " HAVING COUNT(*) > 15" 1047 | ] 1048 | }, 1049 | { 1050 | "cell_type": "markdown", 1051 | "metadata": { 1052 | "slideshow": { 1053 | "slide_type": "subslide" 1054 | } 1055 | }, 1056 | "source": [ 1057 | "## Practice\n", 1058 | "Retrieve product IDs for products with at least 100 total units ordered in OrderDetails" 1059 | ] 1060 | }, 1061 | { 1062 | "cell_type": "markdown", 1063 | "metadata": { 1064 | "slideshow": { 1065 | "slide_type": "notes" 1066 | } 1067 | }, 1068 | "source": [ 1069 | "### Answers\n", 1070 | "SELECT ProductID, SUM(Quantity) \n", 1071 | "FROM OrderDetails \n", 1072 | "GROUP BY ProductID \n", 1073 | "HAVING SUM(QUANTITY) >= 100" 1074 | ] 1075 | }, 1076 | { 1077 | "cell_type": "markdown", 1078 | "metadata": { 1079 | "slideshow": { 1080 | "slide_type": "slide" 1081 | } 1082 | }, 1083 | "source": [ 1084 | "# UNION\n", 1085 | "UNION combines the results of 2+ SELECT queries.\n", 1086 | "\n", 1087 | "Requirements: same number, type, and order of columns\n", 1088 | "\n", 1089 | "Default is only distinct results; use UNION ALL for all results" 1090 | ] 1091 | }, 1092 | { 1093 | "cell_type": "markdown", 1094 | "metadata": { 1095 | "slideshow": { 1096 | "slide_type": "fragment" 1097 | } 1098 | }, 1099 | "source": [ 1100 | "## Example\n", 1101 | "To retrieve a combined list of all cities which have suppliers AND customers:\n", 1102 | "\n", 1103 | " SELECT City from Customers\n", 1104 | " UNION\n", 1105 | " SELECT City from Suppliers\n", 1106 | " ORDER BY City" 1107 | ] 1108 | }, 1109 | { 1110 | "cell_type": "markdown", 1111 | "metadata": { 1112 | "slideshow": { 1113 | "slide_type": "fragment" 1114 | } 1115 | }, 1116 | "source": [ 1117 | "To retrieve a combined list of all cities which have suppliers OR customers: \n", 1118 | "\n", 1119 | " SELECT City from Customers \n", 1120 | " UNION ALL \n", 1121 | " SELECT City from Suppliers \n", 1122 | " ORDER BY City " 1123 | ] 1124 | }, 1125 | { 1126 | "cell_type": "markdown", 1127 | "metadata": { 1128 | "slideshow": { 1129 | "slide_type": "subslide" 1130 | } 1131 | }, 1132 | "source": [ 1133 | "## Practice\n", 1134 | "Retrieve a list of countries containing both suppliers and customers." 1135 | ] 1136 | }, 1137 | { 1138 | "cell_type": "markdown", 1139 | "metadata": { 1140 | "slideshow": { 1141 | "slide_type": "notes" 1142 | } 1143 | }, 1144 | "source": [ 1145 | "### Answers\n", 1146 | "SELECT Country from Customers \n", 1147 | "UNION \n", 1148 | "SELECT Country from Suppliers \n", 1149 | "ORDER BY City " 1150 | ] 1151 | }, 1152 | { 1153 | "cell_type": "markdown", 1154 | "metadata": { 1155 | "slideshow": { 1156 | "slide_type": "slide" 1157 | } 1158 | }, 1159 | "source": [ 1160 | "# Combining commands\n", 1161 | "\n", 1162 | "You can combine as many commands as you like to make your queries as specific as you require. Pay careful attention to the order of the commands." 1163 | ] 1164 | }, 1165 | { 1166 | "cell_type": "markdown", 1167 | "metadata": { 1168 | "slideshow": { 1169 | "slide_type": "fragment" 1170 | } 1171 | }, 1172 | "source": [ 1173 | "## Command order of operations\n", 1174 | "SELECT (TOP) \n", 1175 | "FROM \n", 1176 | "WHERE (BETWEEN | LIKE | IN) \n", 1177 | "GROUP BY \n", 1178 | "HAVING \n", 1179 | "ORDER BY (ASC | DESC) \n", 1180 | "LIMIT \n", 1181 | "UNION (ALL) " 1182 | ] 1183 | }, 1184 | { 1185 | "cell_type": "markdown", 1186 | "metadata": { 1187 | "slideshow": { 1188 | "slide_type": "fragment" 1189 | } 1190 | }, 1191 | "source": [ 1192 | "## Practice\n", 1193 | "Retrieve a table with two columns: the customer's name, and the total number of orders made by that customer. " 1194 | ] 1195 | }, 1196 | { 1197 | "cell_type": "markdown", 1198 | "metadata": { 1199 | "slideshow": { 1200 | "slide_type": "notes" 1201 | } 1202 | }, 1203 | "source": [ 1204 | "### Answers" 1205 | ] 1206 | }, 1207 | { 1208 | "cell_type": "markdown", 1209 | "metadata": { 1210 | "slideshow": { 1211 | "slide_type": "slide" 1212 | } 1213 | }, 1214 | "source": [ 1215 | "# Quiz\n", 1216 | "Test your SQL knowledge here:\n", 1217 | "https://goo.gl/forms/jgPcRXjX5QzDsQqE3" 1218 | ] 1219 | }, 1220 | { 1221 | "cell_type": "markdown", 1222 | "metadata": { 1223 | "slideshow": { 1224 | "slide_type": "slide" 1225 | } 1226 | }, 1227 | "source": [ 1228 | "# More practice\n", 1229 | "1. Return a Table with the following 3 columns: CustomerID, CustomerName, Number of Orders\n", 1230 | "Have the table sorted by Number of Orders with the most orders at the top. Only include repeat customers\n", 1231 | "\n", 1232 | "2. Return a Table with the following 3 columns: ProductID, ProductName, Qty Sold\n", 1233 | "Return only the top 10 products in descending order based on quantity sold.\n", 1234 | "\n", 1235 | "3. Find out who your top 5 customers are based on how much money they've spent." 1236 | ] 1237 | }, 1238 | { 1239 | "cell_type": "markdown", 1240 | "metadata": { 1241 | "slideshow": { 1242 | "slide_type": "notes" 1243 | } 1244 | }, 1245 | "source": [ 1246 | "# Creating a table\n", 1247 | "You can create a new table in the database and initialize it with empty columns." 1248 | ] 1249 | }, 1250 | { 1251 | "cell_type": "markdown", 1252 | "metadata": { 1253 | "slideshow": { 1254 | "slide_type": "notes" 1255 | } 1256 | }, 1257 | "source": [ 1258 | "## Example\n", 1259 | " CREATE TABLE table_name (\n", 1260 | " column1 datatype,\n", 1261 | " column2 datatype,\n", 1262 | " column3 datatype,\n", 1263 | " ....\n", 1264 | " );" 1265 | ] 1266 | }, 1267 | { 1268 | "cell_type": "markdown", 1269 | "metadata": { 1270 | "slideshow": { 1271 | "slide_type": "notes" 1272 | } 1273 | }, 1274 | "source": [ 1275 | "## Practice" 1276 | ] 1277 | }, 1278 | { 1279 | "cell_type": "markdown", 1280 | "metadata": { 1281 | "slideshow": { 1282 | "slide_type": "notes" 1283 | } 1284 | }, 1285 | "source": [ 1286 | "### Answers" 1287 | ] 1288 | }, 1289 | { 1290 | "cell_type": "markdown", 1291 | "metadata": { 1292 | "slideshow": { 1293 | "slide_type": "notes" 1294 | } 1295 | }, 1296 | "source": [ 1297 | "# Primary keys\n", 1298 | "A primary key is an identifier unique to that particular record. Each table can have only one primary key." 1299 | ] 1300 | }, 1301 | { 1302 | "cell_type": "markdown", 1303 | "metadata": { 1304 | "slideshow": { 1305 | "slide_type": "notes" 1306 | } 1307 | }, 1308 | "source": [ 1309 | "## Example\n", 1310 | "While creating a table:\n", 1311 | "\n", 1312 | " CREATE TABLE Persons (\n", 1313 | " ID int NOT NULL,\n", 1314 | " LastName varchar(255) NOT NULL,\n", 1315 | " FirstName varchar(255),\n", 1316 | " Age int,\n", 1317 | " PRIMARY KEY (ID)\n", 1318 | " )\n", 1319 | "\n", 1320 | "Adding to existing table:\n", 1321 | "\n", 1322 | " ALTER TABLE Persons\n", 1323 | " ADD PRIMARY KEY (ID);\n", 1324 | "\n", 1325 | "The format varies slightly here depending on the type of server. \n" 1326 | ] 1327 | }, 1328 | { 1329 | "cell_type": "markdown", 1330 | "metadata": { 1331 | "slideshow": { 1332 | "slide_type": "notes" 1333 | } 1334 | }, 1335 | "source": [ 1336 | "## Practice" 1337 | ] 1338 | }, 1339 | { 1340 | "cell_type": "markdown", 1341 | "metadata": { 1342 | "slideshow": { 1343 | "slide_type": "notes" 1344 | } 1345 | }, 1346 | "source": [ 1347 | "### Answers" 1348 | ] 1349 | } 1350 | ], 1351 | "metadata": { 1352 | "anaconda-cloud": {}, 1353 | "celltoolbar": "Slideshow", 1354 | "kernelspec": { 1355 | "display_name": "Python [Root]", 1356 | "language": "python", 1357 | "name": "Python [Root]" 1358 | }, 1359 | "language_info": { 1360 | "codemirror_mode": { 1361 | "name": "ipython", 1362 | "version": 3 1363 | }, 1364 | "file_extension": ".py", 1365 | "mimetype": "text/x-python", 1366 | "name": "python", 1367 | "nbconvert_exporter": "python", 1368 | "pygments_lexer": "ipython3", 1369 | "version": "3.5.2" 1370 | } 1371 | }, 1372 | "nbformat": 4, 1373 | "nbformat_minor": 0 1374 | } 1375 | --------------------------------------------------------------------------------