High Tech Hope Video Notes


Video 1 - Introduction to Databases

Agenda

Why should I learn this stuff?
Database definitions
I don't have a server!

Why should I learn this stuff?

Everything is stored electronically; a lot of it is stored in databases
Maybe there is information stored in there that you need to automate your work

Database Definitions

Database
An organized way to store data in tables and columns
RDBMS
Relational Database Management System
SQL Server
Microsoft's RDBMS
Oracle
Another RDBMS
SQL Server Management Studio
SSMS
Tool we use to work with SQL Server
OLTP Database
Online transaction processing database
I.E. buying something from a website, adding a new employee to the system
A database where the work is happening

More Definitions

OLAP Database
Online Analytical Processing
An efficient reporting database
Might be called a data warehouse
Data is stored differently than an OLTP database
Normalized
Making database efficient for inserting and updating new data
SQL
Structured Query Language
Standard language used to manipulate databases
Every database system adds its own additional features to it
T-SQL
SQL Server's version of SQL
Transact SQL; Microsoft's version of SQL
Table
How we store data
Every properly designed database has a table for each object
Object
Grid of columns and rows
Column
How we setup our data
Can apply rules to them
Row
Information about a particular instance
I.E. a row for each customer

Even more...

Primary Key
A column, one or a combination of columns, that uniquely defines the row
Foreign Key
A column in a table that points to the primary key in another table
I.E. Order table has one column, CustomerID, that points back to one row in the Customer table
Index
Similar to an index in the back of a book
Quick search to jump right to the page (or row) you want
Query
Retrieve or manipulate data in our database

Four types of queries:

SELECT
Used to retrieve data
INSERT
Inserting new rows into our table
UPDATE
Modify existing rows
DELETE
Remove existing rows

I don't have a server!

Search for "SQL Server Virtual Labs"
You can take them for a spin for free
Live in the cloud
Created on the fly automatically
When you close it up, the virtual computer is destroyed
Use IE & do bing search for SQL Server Virtual Labs
Look for one that has the word "report" in it
Hotlaunchpad?
Opens a VM and a manual
Scroll until you find the info on how to login to the VM
(Mine automatically logged me in)
Had to read doc instructions because her instructions were different to launch SQL Server 2008 R2 Management Studio
My VM has 2012?
She goes to the start menu, all programs, SQL Server 2008 R2, SQL Server 2008 R2 Management Studio
Hit Connect button
Server name: DEMO2010A
Expand Database
AdventureWorks2008R2 & AdventureWorksDW2008R2 are the ones to work with
Expand, Tables, HumResources.Employee, Right Click, Select Top 1000 Rows
Query window pops open
Top shows SELECT statement, bottom shows table

For more information...

http://www.pragmaticworks.com
Kathi Kellenberger
kkellenberger@pragmaticworks.com
Can email her questions about what we learned here today
She can't answer questions on problems with the virtual labs

Video 2 - SELECT Part 1

Agenda

Tools
so we can follow along or work on our own to learn more
Hello, World!
Retrieving Data
Filtering Data
Ordering Data

Tools

SQL Server
If you have a SQL Server available, download the sample OLTP database, AdventureWorks, from www.Codeplex.com
Figure out which version of SQL server you are running and download that specific version
You can start with anything from 2008 to 2012 to follow along

Tools

SQL Server free virtual labs
http://www.microsoft.com/sqlserver/en/us/learning-center/virtual-labs.aspx
Go back to first video to learn more on how to do this

Demos, and More Demos!

She goes to the start menu, all programs, SQL Server 2008 R2, SQL Server 2008 R2 Management Studio
AdventureWorks2008R2 is the ones to work with
(I went to MSBI box to get into SSMS)
How to print something on the screen
Click New Query
Select line you want to run, otherwise everything will run
Typed in PRINT 'Hello, World!'
Highlight it
Press Execute button
Hello, World! displays in Messages tab
Type in SELECT 'Hello, World!'
Highlight it
Execute
This time the results come back in a grid
There are buttons up top that let you select whether you want the results to go to text, grid or a file
Selected text and you get text in a Results tab at bottom of screen
Type in

USE AdventureWorks2012
GO
GO is a batch separator (separate batches of information from one another)
If you switch to the master database & click Execute it pops right to AdventureWorks2012
In Object Explorer, expand Databases, AdventureWorks2012, Tables
There are many tables listed, grouped by area of the company
This is called a schema
A schema is the way to group objects in a database so you can group ownership and permissions in an easy way
This is not always used in databases
Sometimes every single table will start with dbo
AdventureWorks is a fictitious company that sells bicycles
When you pull data from a table you have to have at least two things:
  1. the word SELECT, (* in this example)
  2. the word FROM, followed by the table name
Fully qualified: Schema.Table
If table name starts with dbo, she may or may not specify dbo
Type in
SELECT * FROM HumanResources.Department
Results to Grid
Highlight and Execute
You get back every column from that table
Expand HumanResources.Department, Columns and you can see the exact columns from the table
Type in
SELECT * FROM Department
Highlight and Execute
You get an Invalid object name error
-- two dashes in front of a line is a single line comment
/* */ is a multi line comment
You almost never should use SELECT *
You don't always want to return every column
There are some performance issues, pulling data you don't need to see
Some data may be confidential
SQL gives you some nice tools to script things
Go the the table & right click it; there are a lot of options, such as
Select top 1000 Rows
Script Table as, SELECT to, New Query Edit Window
It generated the following SQL code:
USE [AdventureWorks2012]
GO

SELECT [DepartmentID]
      ,[Name]
      ,[GroupName]
      ,[ModifiedDate]
FROM [HumanResources].[Department]
GO
She commented out some of the lines
She deleted some of the lines
SQL Server has IntelliSense
Start typing in the column name and it can auto-complete
No excuse for writing queries with *
The next thing to learn is filtering the data
Use the WHERE clause to compare one of the columns to a value
[] surrounding columns are optional except for column names that are not legal; I.E. a column name with a space in it or a reserved keyword in it
Type in
SELECT [BusinessEntityID]
     , [JobTitle]
     , [BirthDate]
     , [MaritalStatus]
     , [Gender]
     , [HireDate]
FROM [HumanResources].[Employee]
Highlight and Execute
All that info comes back
Type in at bottom
WHERE [BusinessEntityID] = 3
Highlight and Execute
Get back a single row
She typed in
WHERE 1 = 1
She got back the entire table
She typed in
WHERE 1 = 2
She got back nothing
If you want to filter on columns that have string type data
Type in
SELECT [BusinessEntityID]
     , [JobTitle]
     , [BirthDate]
     , [MaritalStatus]
     , [Gender]
     , [HireDate]
FROM [HumanResources].[Employee]
WHERE Gender = 'F'
Highlight and Execute
Only get back 84 rows
Filter on dates
Type in
SELECT [BusinessEntityID]
     , [JobTitle]
     , [BirthDate]
     , [MaritalStatus]
     , [Gender]
     , [HireDate]
FROM [HumanResources].[Employee]
WHERE BirthDate BETWEEN '1/1/1970' AND '12/31/1970'
Highlight and Execute
16 people born in 1970
BETWEEN is inclusive
We can do lots of things with WHERE clauses
Will go more in-depth in later videos
How to sort data in the database
We use the ORDER BY clause
Can specify column not listed if you choose
Type in
SELECT [BusinessEntityID]
     , [JobTitle]
     , [BirthDate]
     , [MaritalStatus]
     , [Gender]
     , [HireDate]
FROM [HumanResources].[Employee]
ORDER BY [BirthDate]
Highlight and Execute
Type in
ORDER BY [HireDate]
Highlight and Execute
Type in
ORDER BY [HireDate] DESC
Can specify more than one column Highlight and Execute Type in
ORDER BY [JobTitle], [BirthDate] DESC
Highlight and Execute
We've learned a lot in this video. We've learned how to:
Find where our tables are
Look at them over in the sidebar
Connect to a specifc database
Print a message on the screen
Select information from a table using a SELECT statement
Filter data
Sort data
Play around and write SELECT statements
Make up some of your own

Video 3 - SELECT Part 2

How to use expressions and functions in your T-SQL statements

Agenda

Tools
Concatenate Columns
Mathematical Operations
Using Functions
CASE

Tools

SQL Server
If you have a SQL Server available, download the sample OLTP database, AdventureWorks, from www.Codeplex.com
Figure out which version of SQL server you are running and download that specific version
You can start with anything from 2008 to 2012 to follow along

Tools

SQL Server free virtual labs
http://www.microsoft.com/sqlserver/en/us/learning-center/virtual-labs.aspx
Go back to first video to learn more on how to do this

Concatenate two columns

Type in
--Concatenating character data
SELECT Name, GroupName,
[Name] + [GroupName]
FROM HumanResources.Department
Highlight and Execute
By using the + sign we can concatenate these two columns together
Creates a third (No column name) with data from these two jammed together
In order to get over this problem of (No column name), you can add an alias
Type in
--Adding an alias
SELECT Name, GroupName,
[Name] + [GroupName] AS "New Name"
FROM HumanResources.Department
Highlight and Execute
Would not have to use quotes around New Name if it didn't have a space in the name
Also can't use any reserved or keywords for alias names
Can also use an alias for any of the other columns
Type in
SELECT Name AS "Old Name", GroupName,
[Name] + [GroupName] AS "New Name"
FROM HumanResources.Department
Highlight and Execute
Same results as last one except we are using alias name
Type in
SELECT Name GroupName,
[Name] + [GroupName] AS "New Name"
FROM HumanResources.Department
Highlight and Execute
GroupName is used as an alias when this is run
This is a very common mistake
Add the comma back and you get what you expect
That's why she likes to use the AS keyword, even though it's optional so that she's very clear in what she's trying to accomplish
Type in
--Add a literal value
SELECT Name OldName, GroupName,
[GroupName] + ': ' + [Name] AS "New Name"
FROM HumanResources.Department
Highlight and Execute
Formats concatenated data in New Name field
This might be something you want to generate for a report
Type in
--Add a number to a string
SELECT Name + DepartmentID
FROM HumanResources.Department
Highlight and Execute
Get error message saying string value cannot be converted to an integer
To get around this, we are going to use a function
Functions are pieces of reusable code
We have two ways we can do this
CAST function
CONVERT function
Type in
--Cast and Convert
SELECT Name + CAST(DepartmentID AS VARCHAR) AS "Cast",
Name + CONVERT(VARCHAR, DepartmentID) AS "Convert"
FROM HumanResources.Department
Highlight and Execute
Gives two columns, Cast and Convert, with same exact results
Type in
--NULLS
SELECT AddressLine1, AddressLine2
FROM Person.Address
Highlight and Execute
AddressLine1 has good data, AddressLine2 has NULL
NULL value means unknown
We don't know if the data exists or not
Let's say we want to append these two columns together
Type in
SELECT AddressLine1, AddressLine2,
AddressLine1 + ' ' + AddressLine2
FROM Person.Address
Highlight and Execute
We see that AddressLine1 + NULL = NULL
Anytime we operate with NULL, we end up with NULL as a result
Scroll down to a line with a value in AddressLine2 and we get what we were after
There are two functions for this
ISNULL
COALESCE

Type in
--ISNULL and COALESCE
SELECT AddressLine1, AddressLine2,
AddressLine1 + ' ' + ISNULL(AddressLine2,'') AS "ISNULL",
AddressLine1 + ' ' + COALESCE(AddressLine2,'') AS "COALESCE"
FROM Person.Address
Highlight and Execute
With ISNULL, we provide two arguments
One is checked to see if it returns a NULL or not
If it does return a NULL then the second argument is the replacement
With COALESCE, we actually have multiple values (more than two)
It will find the first non-NULL value
For this particular query, ISNULL and COALESCE are working exactly the same
Type in
--More COALESCE
SELECT Size, Class, Color
    ,COALESCE(Size,Class,Color) AS "COALESCE"
FROM Production.Product
WHERE Color IS NOT NULL OR Size IS NOT NULL
OR Class IS NOT NULL
Highlight and Execute
Most of the vaules are NULL for these three columns
We are using a WHERE clause to filter out where all 3 are NULL
COALESCE is looking through the values and returning the first non-NULL value
There's a new function in SQL Server 2012 called CONCAT
With CONCAT we can supply the values we want to concatenate and we don't have to worry about NULL
It will change any of the NULL values to an empty string
Cool new feature
Type in
/* NEW FUNCTION IN SQL SERVER 2012!

CONCAT(Co11,Co12,Co13)

*/
What if we are working with numbers?
Type in
--Mathematical operators
SELECT BusinessEntityID,
BusinessEntityID * 2 AS "Multiply",
BusinessEntityID / 2 AS "Divide",
BusinessEntityID + 2 AS "Add",
BusinessEntityID - 2 AS "Subtract",
BusinessEntityID % 2 AS "Modulo"
FROM HumanResources.Employee
Highlight and Execute
Modulo is the remainder
There are a number of mathematical functions you can use as well
Type in
--Mathematical functions
SELECT BusinessEntityID,
SQUARE(BusinessEntityID) AS "Square",
SQRT(BusinessEntityID) AS "SQRT",
ROUND(SQRT(BusinessEntityID),2) AS "Round"
FROM HumanResources.Employee
Highlight and Execute
In one example, the SQRT function is nested inside the ROUND function
ROUND rounds the SQRT decimals to two places
There are many more mathematical functions you can look up online
She displayed a list of them from the online documentation
You can also use functions with strings
Type in
--String functions
SELECT Description, LEFT(Description,10) AS "Left 10",
SUBSTRING(Description,11,30) AS "Substring",
CHARINDEX('Alu',Description) AS "Charindex"
FROM Production.ProductDescription
Highlight and Execute
LEFT selects just the first 10 chars from the string
SUBSTRING starts from the middle of the string
CHARINDEX allows us to search for a char or number of characters and returns the position
There are many more string functions available that you can look up online
There are many functions you can use to work with dates
Type in
--Date functions
SELECT BirthDate, HireDate,
DATEADD(yyyy,10,HireDate) AS "DateAdd",
DATEDIFF(YYYY,BirthDate,HireDate) AS "DateDiff",
YEAR(BirthDate) AS "Year",
GETDATE()
FROM HumanResources.Employee
Highlight and Execute
DATEADD adds 10 years to the HireDate
DATEDIFF finds out how many years between BirthDate and HireDate
YEAR returns just the year
GETDATE returns the current date and time
DATEDIFF is not calcuating the real difference between the entire date
Type in
/* NEW FUNCTIONS in SQL Server 2012!!!

FORMAT, EOMONTH, DATEFROMPARTS

*/
FORMAT is just like the format function in .Net
EOMONTH returns the last day of the month
DATEFROMPARTS has several sub-functions
In versions earlier than 2012 you can use the CONVERT function with the optional STYLE parameter to specify how to format your date
Type in
--Convert
SELECT BirthDate,
CONVERT(VARCHAR,BirthDate,111) AS "Slashes",
CONVERT(VARCHAR,BirthDate,107) AS "Spelled out"
FROM HumanResources.Employee
Highlight and Execute
Works in 2012!
BirthDate is stored as a number but is presented in human readable form
Take a look at books online for the different styles available
Type in
--CASE
SELECT BusinessEntityID,
CASE BusinessEntityID % 2 WHEN 0 THEN 'Even'
WHEN 1 THEN 'Odd' Else 'UNKNOWN' END AS OddOREven
FROM HumanResources.Employee
Highlight and Execute
Type in
/* NEW FUNCTIONS IN SQL SERVER 2012

IIF

*/
IIF - in-line IF
Found in many other languages
Same idea as using CASE
We can use expressions and functions in the other parts of a SQL Server statement as well
Most of those are too advanced for this particular video but she does have one easy example she wants to show us
Type in
--Order by
SELECT HireDate
FROM HumanResources.Employee
ORDER BY MONTH(HireDate)
Highlight and Execute
Notice that all of the January's are returned first, then the Feburary's, etc.

Video 4 - SELECT Part 3

In this video, we'll learn more about the WHERE clause

Agenda

Tools
Using functions and expressions
NULL
Multiple conditions
The IN list

Tools

SQL Server
If you have a SQL Server available, download the sample OLTP database, AdventureWorks, from www.Codeplex.com
Figure out which version of SQL server you are running and download that specific version
You can start with anything from 2008 to 2012 to follow along

Tools

SQL Server free virtual labs
http://www.microsoft.com/sqlserver/en/us/learning-center/virtual-labs.aspx
Go back to first video to learn more on how to do this

Demos, and More Demos!

Type in
--Using an expression in the WHERE clause
SELECT BusinessEntityID
FROM HumanResources.Employee
WHERE BusinessEntityID % 2 = 0
Highlight and Execute
Get back 145 rows with WHERE clause, 290 without
Comparing an expresson to a value
Type in
--Using an expression in the WHERE clause
SELECT BusinessEntityID
FROM HumanResources.Employee
WHERE BusinessEntityID % 2 != 0
Highlight and Execute
!= is not equals
Should give you the opposite of the previous code's results
<> is the same as != (from Visual Basic)
Type in
--Using a function in the WHERE clause
SELECT BusinessEntityID, HireDate
FROM HumanResources.Employee
WHERE YEAR(HireDate) = 2003
Highlight and Execute
This is not always a great idea
If you have an index on the column that you use with your function, that will cause SQL Server to ignore that index
SQL Server has to apply the function to every single row
In this example the field isn't an index
A better way to accomplish the same thing
Type in
--A better way to write this!
SELECT BusinessEntityID, HireDate
FROM HumanResources.Employee
WHERE HireDate >= '1/1/2003' AND HireDate < '1/1/2004'
Highlight and Execute
We get the same answer as previous example
Another way to do this is using the BETWEEN operator
Type in
--BETWEEN
SELECT BusinessEntityID, HireDate
FROM HumanResources.Employee
WHERE HireDate BETWEEN '1/1/2003' AND '12/31/2003'
Highlight and Execute
We get the same answer as previous example
Some other examples with BETWEEN
Type in
SELECT BusinessEntityID, HireDate
FROM HumanResources.Employee
WHERE BusinessEntityID BETWEEN 10 AND 15
Highlight and Execute
Type in
SELECT BusinessEntityID, HireDate
FROM HumanResources.Employee
WHERE BusinessEntityID BETWEEN 15 AND 10
Highlight and Execute
Gives no results
Type in
SELECT BusinessEntityID, HireDate
FROM HumanResources.Employee
WHERE BusinessEntityID NOT BETWEEN 10 AND 15
Highlight and Execute
The NOT operator is used a lot in queries
Type in
SET STATISTICS IO ON
Highlight and Execute
Command(s) completed successfully
Helps you figure out how well your queries are performing or compare two different queries
Type in
SELECT FirstName, LastName
FROM Person.Person
WHERE LEFT(Lastname,1) ='M'
Highlight and Execute
Looks for all the last names that end with M
There is an index on LastName
1550 rows
Look in the Messages tab
Focus on logical reads 106
Another way to write this query using LIKE
Type in
--Like
SELECT FirstName, LastName
FROM Person.Person
WHERE LastName LIKE 'M%'
Highlight and Execute
There are other ways to use LIKE and other ways to specify all characters
We still get back 1550 rows, but logical reads 12
That means this query performs much better
Remember that our index is a compound index conataining last name and first name
Type in
--The second column in the index
SELECT FirstName, LastName
FROM Person.Person
WHERE FirstName = 'Zheng'
Highlight and Execute
logical reads 106
Keep in mind indexes might be in place to help the performance of your query and there are things you can do to figure out if the way you are writing it is going to have good performance or not
Type in
--Nulls
--19614 values
SELECT AddressLine1, AddressLine2
FROM Person.Address
Highlight and Execute
19614 rows
Type in
--4 values
SELECT AddressLine1, AddressLine2
FROM Person.Address
WHERE AddressLine2 = '# 4'
Highlight and Execute
4 rows
Type in
--358 values
SELECT AddressLine1, AddressLine2
FROM Person.Address
WHERE AddressLine2 <> '# 4'
Highlight and Execute
358 rows back
That doesn't make sense
Theoretically it should be the number of the entire table minus the number of rows found in the previous query
The problem is that we cannot compare anything to NULL
The way to do this
Type in
SELECT AddressLine1, AddressLine2
FROM Person.Address
WHERE AddressLine2 <> '# 4'
OR AddressLine2 IS NULL
Highlight and Execute
19610 rows
Another way to do this is with ISNULL function
Type in
SELECT AddressLine1, AddressLine2
FROM Person.Address
WHERE ISNULL(AddressLine2,'') <> '# 4'
Highlight and Execute
The empty string '' can be compared to '# 4'
19610 rows
Make sure you don't have an index on that AddressLine2 column
Type in
--Multiple conditions
SELECT FirstName, LastName
FROM Person.Person
WHERE LastName = 'Adams' AND FirstName = 'Edward'
Highlight and Execute
1 entry
2 logical reads
Type in
--Multiple conditions
SELECT FirstName, LastName
FROM Person.Person
WHERE LastName = 'Adams' OR FirstName = 'Edward'
Highlight and Execute
157 rows
108 logical reads
That's because with the AND query we were able to use the index to find the rows
Type in
/*Return a list of names the last name
must be Adams or Brown, the first name 
must be Edward
*/
SELECT FirstName, LastName
FROM Person.Person
WHERE LastName = 'Adams' OR LastName = 'Brown'
AND FirstName = 'Edward'
Highlight and Execute
87 rows
A bunch of people, only 1 Edward
SQL Server is trying to figure out what you are trying to do here
It processes the AND first, then the OR
Type in
SELECT FirstName, LastName
FROM Person.Person
WHERE LastName = 'Adams' OR FirstName = 'Edward'
AND LastName = 'Brown'
Highlight and Execute
93 rows, still not right
Use () to force SQL Server to evaluate differently
Type in
SELECT FirstName, LastName
FROM Person.Person
WHERE (LastName = 'Adams' OR LastName = 'Brown')
AND FirstName = 'Edward'
Highlight and Execute
2 rows
Type in
SELECT FirstName, LastName
FROM Person.Person
WHERE LastName IN ('Adams','Brown')
AND FirstName = 'Edward'
Highlight and Execute
2 rows, same results as previous

Video 5 - JOINing Tables Part 1

Learn how to JOIN two or more tables in one query

Agenda

Tools

Why do we need to JOIN tables?
How to JOIN tables
Examples

Tools

SQL Server
If you have a SQL Server available, download the sample OLTP database, AdventureWorks, from www.Codeplex.com
Figure out which version of SQL server you are running and download that specific version
You can start with anything from 2008 to 2012 to follow along

Tools

SQL Server free virtual labs
http://www.microsoft.com/sqlserver/en/us/learning-center/virtual-labs.aspx
Go back to first video to learn more on how to do this

Why do we need to JOIN tables?

Why not have all the data in 1 gigantic table?
App wouldn't perform very well
Designed via a process called normalization
One table for each type of object
Key icon next to a field means that field is a primary key

How to JOIN Tables

Old syntax:
SELECT col1, col2
FROM table1, table2
WHERE col1 = col2
Preferred syntax:
SELECT col1, col2
FROM table1 INNER JOIN table2
ON col1 = col2

Column names of primary key and foreign key can be identical or not
Will explain reason why she doesn't like old syntax later

Demos, and More Demos!

Type in
/*
Requirements: Create a list of current employees,
their names, titles and departments
*/
First thing is to take a look at the tables we have available
Type in
SELECT * FROM HumanResources.Employee
Highlight and Execute
290 rows
Contains Job Title
We will have to pull data from another table
Type in
--Join the Employee table to the Person.Person
--table to display the employee name with the title.
SELECT emp.BusinessEntityID AS EmployeeID, contact.FirstName,
contact.Lastname, emp.JobTitle
FROM HumanResources.Employee AS emp
INNER JOIN Person.Person AS contact
ON emp.BusinessEntityID = contact.BusinessEntityID
ORDER BY emp.BusinessEntityID
Highlight and Execute
She had to put emp or contact in front of BusinessEntityID becuase the field name is exactly the same in both tables & this qualifies where the data is coming from
She made emp an alias for HumanResources.Employee
She made contact an alias for Person.Person
The word INNER is optional
She takes a step-by-step approach to writing the queries
Still have 290 rows
Next thing is to include their departments
There's an intermediate table called EmployeeDepartmentHistory that we have to JOIN to
This table could have more than one row for an employee
Type in
SELECT emp.BusinessEntityID AS EmployeeID, contact.FirstName,
contact.Lastname, emp.JobTitle,
edh.DepartmentID, edh.StartDate, edh.EndDate
FROM HumanResources.Employee AS emp
INNER JOIN Person.Person AS contact
ON emp.BusinessEntityID = contact.BusinessEntityID
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON emp.BusinessEntityID = edh.BusinessEntityID
WHERE edh.EndDate IS NULL
Highlight and Execute (except for last WHERE line)
296 rows
Two rows for Rob Walters
A lot of EndDate fields are NULL
Rob Walters got transferred from dept 1 to dept 2
Highlight and Execute (include last WHERE line)
290 rows
Rob Walters only shows up once
Type in
SELECT emp.BusinessEntityID AS EmployeeID, contact.FirstName,
contact.Lastname, emp.JobTitle,
dept.DepartmentID, dept.Name
FROM HumanResources.Employee AS emp
INNER JOIN Person.Person AS contact
ON emp.BusinessEntityID = contact.BusinessEntityID
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON emp.BusinessEntityID = edh.BusinessEntityID
INNER JOIN HumanResources.Department AS dept
ON edh.DepartmentID = dept.DepartmentID
WHERE edh.EndDate IS NULL
ORDER BY emp.BusinessEntityID
Highlight and Execute
Added dept name
Switched to the dept table
May want to put in an alias for dept.Name
We are using EmployeeDepartmentHistory but not displaying any columns from that table
That is often the case when working with an intermediary table
Now that we have a good query that fulfills our requirements, we will learn how to do it using the older syntax
Type in
--The "other" way
SELECT emp.BusinessEntityID AS EmployeeID, contact.FirstName,
contact.LastName, emp.JobTitle,
dept.DepartmentID, dept.Name
FROM HumanResources.Employee AS emp,
Person.Person AS contact,
HumanResources.EmployeeDepartmentHistory AS edh,
HumanResources.Department AS dept
WHERE edh.EndDate IS NULL
AND emp.BusinessEntityID = contact.BusinessEntityID
AND emp.BusinessEntityID = edh.BusinessEntityID
AND edh.DepartmentID = dept.DepartmentID
ORDER BY emp.BusinessEntityID
Highlight and Execute
290 rows
This query works however it is written differently
All JOIN conditions listed in the WHERE clause
Doesn't like it because
Her WHERE conditions and JOIN conditions are mixed together; would rather keep them separate for clarity
When you JOIN this way, you don't have to have a WHERE clause at all
Similar query but left out one of the JOIN conditions
Type in
--What if I forget one of the join condtions?
SELECT emp.BusinessEntityID AS EmployeeID, contact.FirstName,
contact.LastName, emp.JobTitle,
dept.DepartmentID,dept.Name
FROM HumanResources.Employee AS emp,
Person.Person AS contact,
HumanResources.EmployeeDepartmentHistory AS edh,
HumanResources.Department AS dept
WHERE edh.EndDate IS NULL
AND emp.BusinessEntityID = contact.BusinessEntityID
AND edh.DepartmentID = dept.DepartmentID
ORDER BY emp.BusinessEntityID
Highlight and Execute
84100 rows!
Very easy to make a mistake with this method
There's other more advanced JOINs we'll talk about in later videos where you can't use this method at all, so better off sticking with the other way

Video 6 - JOINing Tables Part 2

Agenda

Tools
OUTER JOIN
Sub-Query
FULL OUTER JOIN
CROSS JOIN

Tools

SQL Server
If you have a SQL Server available, download the sample OLTP database, AdventureWorks, from www.Codeplex.com
Figure out which version of SQL server you are running and download that specific version
You can start with anything from 2008 to 2012 to follow along

Tools

SQL Server free virtual labs
http://www.microsoft.com/sqlserver/en/us/learning-center/virtual-labs.aspx
Go back to first video to learn more on how to do this

Demos, and More Demos!

Type in
--The list of customers with the sales order ID
SELECT c.CustomerID, c.AccountNumber, o.SalesOrderID
FROM Sales.Customer AS c
INNER JOIN Sales.SalesOrderHeader AS o
ON c.CustomerID = o.CustomerID
Highlight and Execute
31465 rows
It's possible that I have some customers that have not placed an order
However, it's not possible to have SalesOrderHeader without a customer
Type in
/*
Display all the customers with orders even
if no orders yet
Using LEFT OUTER JOIN
*/
SELECT c.CustomerID, c.AccountNumber, o.SalesOrderID
FROM Sales.Customer AS c
LEFT OUTER JOIN Sales.SalesOrderHeader AS o
ON c.CustomerID = o.CustomerID
Highlight and Execute
The OUTER keyword is optional
Will get all the customer records returned even if they don't have a match in SalesOrderHeader table
We get a bunch of NULL values in the SalesOrderID column
32166 rows
700 more than previous
RIGHT OUTER JOIN gets all the rows from the table on the right even if there's not a match
Type in
--Using LEFT OUTER JOIN
SELECT c.CustomerID, c.AccountNumber, o.SalesOrderID
FROM Sales.SalesOrderHeader AS o
RIGHT OUTER JOIN Sales.Customer AS c
ON c.CustomerID = o.CustomerID
Highlight and Execute
She likes to use LEFT OUTER JOIN because she likes to get the results from the most important table first
What if we just want a list of customers who placed orders?
Use a sub-query
Type in
--Use a sub-query to find the customers
--Who have placed an order
SELECT CustomerID, AccountNumber
FROM Sales.Customer
WHERE CustomerID IN (SELECT CustomerID FROM Sales.SalesOrderHeader)
Highlight and Execute
Sub-query is surrounded by () and proceeded by the word IN
Can only include one column here; cannot have multiple columns
19119 rows
Every customer is only listed one time
Not doing a JOIN
Not included any columns from SalesOrderHeader table
Type in
/*
Number of orders: 31465
Number of customers: 19820 [NOTE: run the first two lines of code above to get this number]
Number of customers with orders: 19119
*/
Type in
--Finding the customers who haven't
--Placed an order
SELECT c.CustomerID, c.AccountNumber
FROM Sales.Customer AS c
LEFT OUTER JOIN Sales.SalesOrderHeader AS o
ON c.CustomerID = o.CustomerID
WHERE o.CustomerID IS NULL
ORDER BY c.CustomerID
Highlight and Execute
701 rows
Type in
--Step 2 get all rows from the left side
SELECT c.CustomerID, c.AccountNumber, o.SalesOrderID
FROM Sales.Customer AS c
LEFT OUTER JOIN Sales.SalesOrderHeader o
ON c.CustomerID = o.CustomerID
ORDER BY c.CustomerID
Highlight and Execute
Type in
--Step 3 filter out rows that are a match
SELECT c.CustomerID, c.AccountNumber, o.SalesOrderID
FROM Sales.Customer AS c
LEFT OUTER JOIN Sales.SalesOrderHeader o
ON c.CustomerID = o.CustomerID
WHERE o.SalesOrderID IS NULL
ORDER BY c.CustomerID
Highlight and Execute
701 rows
At this point, since all the values in SalesOrderID are NULL, we can get rid of the last column if we want by removing o.SalesOrderID from the first SELECT query line in our code
We can also use a sub-query to do this
Type in
--Use a sub-query
SELECT CustomerID, AccountNumber
FROM Sales.Customer
WHERE CustomerID NOT IN
(SELECT CustomerID FROM Sales.SalesOrderHeader)
Highlight and Execute
Very similar to earlier sub-query except for NOT
Type in
/*
FULL OUTER JOIN
Hard to find a reason to do this in a properly 
designed database, so we'll create a table that doesn't belong
*/
IF OBJECT_ID('DepartmentValue') IS NOT NUL
DROP TABLE DepartmentValue

CREATE TABLE DepartmentValue(DepartmentID int,SomeValue varchar(50))
INSERT INTO DepartmentValue (DepartmentID, SomeValue)
VALUES (1, 'one'), (2, 'two'), (20, 'twenty')
Highlight and Execute
Type in
SELECT * FROM DepartmentValue
Highlight and Execute
Type in
--Do an INNER JOIN
SELECT d.DepartmentID, d.Name, dv.SomeValue
FROM HumanResources.Department AS d
INNER JOIN DepartmentValue AS dv
ON d.DepartmentID = dv.DepartmentID
Highlight and Execute
Type in
--Do an LEFT OUTER JOIN
SELECT d.DepartmentID, d.Name, dv.SomeValue
FROM HumanResources.Department AS d
LEFT OUTER JOIN DepartmentValue AS dv
ON d.DepartmentID = dv.DepartmentID
Highlight and Execute
16 rows, 14 do not match
Type in
--A RIGHT OUTER JOIN
SELECT d.DepartmentID, d.Name, dv.SomeValue, dv.DepartmentID
FROM HumanResources.Department AS d
RIGHT OUTER JOIN DepartmentValue AS dv
ON d.DepartmentID = dv.DepartmentID
Highlight and Execute
Gives us the two rows that match plus an extra one that does not match
Type in
--FULL OUTER JOIN
SELECT d.DepartmentID, d.Name, dv.SomeValue, dv.DepartmentID
FROM HumanResources.Department AS d
FULL OUTER JOIN DepartmentValue AS dv
ON d.DepartmentID = dv.DepartmentID
Highlight and Execute
17 rows
first two rows - equal match of the two tables
14 rows that have no matching value in the DepartmentValue table
One row from DepartmentValue table that doesn't have a match in Department
You'll very very rarely see something like this
Most of the time if you have two tables that have a one to many JOIN, I.E. a customer can have one to many orders.
CROSS JOIN is pretty rare
Can JOIN two tables that don't have a relationship
Type in
--Using CROSS JOIN to join two tables with no relationship
--This is a Cartesian Product!

--First, how many rows in the Location and Product tables?
SELECT * FROM Production.Location --14
SELECT * FROM Production.Product --504
Highlight and Execute
Type in
--This join is like multiplying the tables together
SELECT l.LocationID, l.Name, p.ProductID, p.Name as ProductName
FROM Production.Product AS p
CROSS JOIN Prodution.Location AS l
Highlight and Execute
We get a row for every product in every location
7056 rows
Type in
SELECT 14 * 504
Highlight and Execute
get answer of 7056

Video 7 - Aggregate Queries

Agenda

Tools
Common Aggregate Functions
Syntax
Examples

Tools

SQL Server
If you have a SQL Server available, download the sample OLTP database, AdventureWorks, from www.Codeplex.com
Figure out which version of SQL server you are running and download that specific version
You can start with anything from 2008 to 2012 to follow along

Tools

SQL Server free virtual labs
http://www.microsoft.com/sqlserver/en/us/learning-center/virtual-labs.aspx
Go back to first video to learn more on how to do this

Common Aggregate Functions

COUNT
MIN
MAX
SUM
AVG

Used to summarize our data or group data into sections

Syntax

SELECT FUNCTION(col1)
FROM table1
SELECT FUNCTION(col1),col2
FROM table1
GROUP BY col2

Demos, and More Demos!

Type In
--Find the count of the rows
SELECT COUNT(*) AS "Cost of Sales"
FROM Sales.SalesOrderHeader
Highlight and Execute
This is one exception where it's always permissible to use the *
Type in
--Look at subTotal
SELECT COUNT(SubTotal) AS "Count of SubTotal",
SUM(SubTotal) AS "Sum of SubTotal",
MIN(SubTotal) AS "Min SubTotal",
MAX(SubTotal) AS "Max SubTotal",
AVG(SubTotal) AS "Avg SubTotal"
FROM Sales.SalesOrderHeader
Highlight and Execute
We get back one row with the answer for the entire table
Type in
--Use an expression
SELECT SUM(SubTotal + TaxAmt + Freight) AS "Total Due"
FROM Sales.SalesOrderHeader
Highlight and Execute
Gives the total due for the entire table
Type in
--Nulls?
SELECT COUNT(*) AS "Cost of rows",
    COUNT(SubTotal) AS "Count of SubTotal",
    COUNT(CurrencyRateID) AS "Count of CurrencyRateID"
FROM Sales.SalesOrderHeader
Highlight and Execute
Aggregate functions ignore NULL values
Type in
SELECT AVG(CurrencyRateID) AS "Avg CurrencyRateID",
SUM(CurrencyRateID)/COUNT(*) AS "Sum/Count of Rows"
FROM Sales.SalesOrderHeader
Highlight and Execute
We get two very different answers due to NULL values being ignored
Be sure to keep this in mind because your requirements will determine how to count the average
Type in
--Display the count of orders for each customer
SELECT CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader
Highlight and Execute
Gives error telling us what we need to do
Type in
--Add a GROUP BY clause
SELECT CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
Highlight and Execute
Get a list of every customer ID and a count of the orders
Type in
--Order by the expression
SELECT CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
ORDER BY COUNT() DESC
Highlight and Execute
Now it's sorted by customers who ordered the most
Type in
--Get some more details about customer
SELECT o.CustomerID, COUNT(*) AS "Order Count",
c.AccountNumber
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY o.CustomerID, c.AccountNumber
Highlight and Execute
Type in
/* Any column that appears in the SELECT list or
ORDER BY clause that is not part of an aggregate
function MUST appear in the GROUP BY clause
*/
SELECT o.CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY o.CustomerID, c.AccountNumber
ORDER BY c.AccountNumber
Highlight and Execute
She commented out c.AccountNumber and we get the earlier error again
Type in
--Don't include anything you don't need
SELECT o.CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY o.CustomerID, c.AccountNumber, o.SalesOrderID
ORDER BY c.AccountNumber
Highlight and Execute
Runs without an error but the results are messed up
Multiple customers with order counts of 1
Get rid of o.SalesOrderID
She starts adding all the columns she needs, copy & pastes into her GROUP BY statement & then starts eliminating all of the aggregate expression
Type in
--Don't use an aggregate function in WHERE
SELECT o.CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
WHERE COUNT(*) > 5
GROUP BY o.CustomerID
Highlight and Execute
We get an error stating an aggregate may not appear in the WHERE clause
The WHERE clause is evaluated and processed before the aggregate is applied
Type in
--Use HAVING
SELECT o.CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY o.CustomerID
HAVING COUNT(*) > 5
Highlight and Execute
HAVING filters out after aggregate queries have been applied
She first ran it without the HAVING statement
19199 rows
Then included the HAVING clause
337 rows
Type in
SELECT o.CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY o.CustomerID
HAVING SUM(SubTotal) > 10000
Highlight and Execute
477 rows
Type in
--Compare to this
SELECT o.CustomerID, COUNT(*) AS "Order Count"
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
WHERE SubTotal > 10000
GROUP BY o.CustomerID
Highlight and Execute
341 rows
In this example are filtering first then applying the aggregate
Previous example applies the aggregate first then filters
We get two different results
Think very carefully about what you're trying to accomplish
Type in
--Let's get a count of orders by customer by year
SELECT c.CustomerID, COUNT(SalesOrderID) AS CountOfSales,
YEAR(o.OrderDate) AS OrderYear
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY c.CustomerID
Highlight and Execute
We get an error
The way around this is
Type in
--Let's get a count of orders by customer by year
SELECT c.CustomerID, COUNT(SalesOrderID) AS CountOfSales,
YEAR(o.OrderDate) AS OrderYear
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY c.CustomerID, o.OrderDate
ORDER BY c.CustomerID, YEAR(o.OrderDate)
Highlight and Execute
Notice that we now have some results we didn't expect
Problem is that we need to
Type in
--Add complete expression to GROUP BY
SELECT c.CustomerID, COUNT(SalesOrderID) AS CountOfSales,
YEAR(o.OrderDate) AS OrderYear
FROM Sales.SalesOrderHeader AS o
INNER JOIN Sales.Customer AS c
ON o.CustomerID = c.CustomerID
GROUP BY c.CustomerID, YEAR(o.OrderDate)
ORDER BY c.CustomerID, YEAR(o.OrderDate)
Highlight and Execute
Now we are getting the exact results we needed
Type in
--Aggregate of character data
SELECT MIN(LastName) AS "Min last name",
MAX(LastName) AS "Max last name"
FROM Person.Person
Highlight and Execute
We get "Abbas" and "Zwilling"
Type in
SELECT AVG(LastName)
FROM Person.Person
Highlight and Execute
We get an error