---------------------------------------------------------------------
-- Microsoft SQL Server 2008 T-SQL Fundamentals
-- Chapter 2 - Single-Table Queries
-- ?2008 Itzik Ben-Gan
---------------------------------------------------------------------
---------------------------------------------------------------------
-- Elements of SELECT Statement
---------------------------------------------------------------------
-- Listing 2-1: Sample Query
USE TSQLFundamentals2008;
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numorders
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate)
HAVING COUNT(*) > 1
ORDER BY empid, orderyear;
---------------------------------------------------------------------
-- The FROM Clause
---------------------------------------------------------------------
SELECT orderid, custid, empid, orderdate, freight
FROM Sales.Orders;
---------------------------------------------------------------------
-- The WHERE Clause
---------------------------------------------------------------------
SELECT orderid, empid, orderdate, freight
FROM Sales.Orders
WHERE custid = 71;
---------------------------------------------------------------------
-- The GROUP BY Clause
---------------------------------------------------------------------
SELECT empid, YEAR(orderdate) AS orderyear
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate);
SELECT
empid,
YEAR(orderdate) AS orderyear,
SUM(freight) AS totalfreight,
COUNT(*) AS numorders
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate);
/*
SELECT empid, YEAR(orderdate) AS orderyear, freight
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate);
*/
SELECT
empid,
YEAR(orderdate) AS orderyear,
COUNT(DISTINCT custid) AS numcusts
FROM Sales.Orders
GROUP BY empid, YEAR(orderdate);
---------------------------------------------------------------------
-- The HAVING Clause
---------------------------------------------------------------------
SELECT empid, YEAR(orderdate) AS orderyear
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate)
HAVING COUNT(*) > 1;
---------------------------------------------------------------------
-- The SELECT Clause
---------------------------------------------------------------------
SELECT orderid orderdate
FROM Sales.Orders;
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numorders
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate)
HAVING COUNT(*) > 1;
/*
SELECT orderid, YEAR(orderdate) AS orderyear
FROM Sales.Orders
WHERE orderyear > 2006;
*/
SELECT orderid, YEAR(orderdate) AS orderyear
FROM Sales.Orders
WHERE YEAR(orderdate) > 2006;
/*
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numorders
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate)
HAVING numorders > 1;
*/
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numorders
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate)
HAVING COUNT(*) > 1;
-- Listing 2-2: Query Returning Duplicate Rows
SELECT empid, YEAR(orderdate) AS orderyear
FROM Sales.Orders
WHERE custid = 71;
-- Listing 2-3: Query With a DISTINCT Clause
SELECT DISTINCT empid, YEAR(orderdate) AS orderyear
FROM Sales.Orders
WHERE custid = 71;
SELECT *
FROM Sales.Shippers;
/*
SELECT orderid,
YEAR(orderdate) AS orderyear,
orderyear + 1 AS nextyear
FROM Sales.Orders;
*/
SELECT orderid,
YEAR(orderdate) AS orderyear,
YEAR(orderdate) + 1 AS nextyear
FROM Sales.Orders;
---------------------------------------------------------------------
-- The ORDER BY Clause
---------------------------------------------------------------------
-- Listing 2-4: Query Demonstrating the ORDER BY Clause
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numorders
FROM Sales.Orders
WHERE custid = 71
GROUP BY empid, YEAR(orderdate)
HAVING COUNT(*) > 1
ORDER BY empid, orderyear;
SELECT empid, firstname, lastname, country
FROM HR.Employees
ORDER BY hiredate;
/*
SELECT DISTINCT country
FROM HR.Employees
ORDER BY empid;
*/
---------------------------------------------------------------------
-- TOP
---------------------------------------------------------------------
-- Listing 2-5: Query Demonstrating the TOP Option
SELECT TOP (5) orderid, orderdate, custid, empid
FROM Sales.Orders
ORDER BY orderdate DESC;
SELECT TOP (1) PERCENT orderid, orderdate, custid, empid
FROM Sales.Orders
ORDER BY orderdate DESC;
-- Listing 2-6: Query Demonstrating TOP with Unique ORDER BY List
SELECT TOP (5) orderid, orderdate, custid, empid
FROM Sales.Orders
ORDER BY orderdate DESC, orderid DESC;
SELECT TOP (5) WITH TIES orderid, orderdate, custid, empid
FROM Sales.Orders
ORDER BY orderdate DESC;
---------------------------------------------------------------------
-- Ranking
---------------------------------------------------------------------
SELECT orderid, custid, val,
SUM(val) OVER() AS totalvalue,
SUM(val) OVER(PARTITION BY custid) AS custtotalvalue
FROM Sales.OrderValues;
SELECT orderid, custid, val,
100. * val / SUM(val) OVER() AS pctall,
100. * val / SUM(val) OVER(PARTITION BY custid) AS pctcust
FROM Sales.OrderValues;
SELECT orderid, custid, val,
ROW_NUMBER() OVER(ORDER BY val) AS rownum,
RANK() OVER(ORDER BY val) AS rank,
DENSE_RANK() OVER(ORDER BY val) AS dense_rank,
NTILE(10) OVER(ORDER BY val) AS ntile
FROM Sales.OrderValues
ORDER BY val;
SELECT orderid, custid, val,
ROW_NUMBER() OVER(PARTITION BY custid
ORDER BY val) AS rownum
FROM Sales.OrderValues
ORDER BY custid, val;
SELECT DISTINCT val, ROW_NUMBER() OVER(ORDER BY val) AS rownum
FROM Sales.OrderValues;
SELECT val, ROW_NUMBER() OVER(ORDER BY val) AS rownum
FROM Sales.OrderValues
GROUP BY val;
---------------------------------------------------------------------
-- Predicates and Operators
---------------------------------------------------------------------
-- Predicates: IN, BETWEEN, LIKE
SELECT orderid, empid, orderdate
FROM Sales.Orders
WHERE orderid IN(10248, 10249, 10250);
SELECT orderid, empid, orderdate
FROM Sales.Orders
WHERE orderid BETWEEN 10300 AND 10310;
SELECT empid, firstname, lastname
FROM HR.Employees
WHERE lastname LIKE N'D%';
-- Comparison operators: =, >, <, >=, <=, <>, !=, !>, !<
SELECT orderid, empid, orderdate
FROM Sales.Orders
WHERE orderdate >= '20080101';
-- Logical operators: AND, OR, NOT
SELECT orderid, empid, orderdate
FROM Sales.Orders
WHERE orderdate >= '20080101'
AND empid IN(1, 3, 5);
-- Arithmetic operators: +, -, *, /, %
SELECT orderid, productid, qty, unitprice, discount,
qty * unitprice * (1 - discount) AS val
FROM Sales.OrderDetails;
-- Operators Precedence
-- AND precedes OR
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE
custid = 1
AND empid IN(1, 3, 5)
OR custid = 85
AND empid IN(2, 4, 6);
-- Equivalent to
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE
( custid = 1
AND empid IN(1, 3, 5) )
OR
( custid = 85
AND empid IN(2, 4, 6) );
-- *, / precedes +, -
SELECT 10 + 2 * 3 -- 16
SELECT (10 + 2) * 3 -- 36
---------------------------------------------------------------------
-- CASE Expression
---------------------------------------------------------------------
-- Simple
SELECT productid, productname, categoryid,
CASE categoryid
WHEN 1 THEN 'Beverages'
WHEN 2 THEN 'Condiments'
WHEN 3 THEN 'Confections'
WHEN 4 THEN 'Dairy Products'
WHEN 5 THEN 'Grains/Cereals'
WHEN 6 THEN 'Meat/Poultry'
WHEN 7 THEN 'Produce'
WHEN 8 THEN 'Seafood'
ELSE 'Unknown Category'
END AS categoryname
FROM Production.Products;
SELECT orderid, custid, val,
CASE NTILE(3) OVER(ORDER BY val)
WHEN 1 THEN 'Low'
WHEN 2 THEN 'Medium'
WHEN 3 THEN 'High'
ELSE 'Unknown'
END AS titledesc
FROM Sales.OrderValues
ORDER BY val;
-- Searched
SELECT orderid, custid, val,
CASE
WHEN val < 1000.00 THEN 'Less then 1000'
WHEN val BETWEEN 1000.00 AND 3000.00 THEN 'Between 1000 and 3000'
WHEN val > 3000.00 THEN 'More than 3000'
ELSE 'Unknown'
END AS valuecategory
FROM Sales.OrderValues;
---------------------------------------------------------------------
-- NULLs
---------------------------------------------------------------------
SELECT custid, country, region, city
FROM Sales.Customers
WHERE region = N'WA';
SELECT custid, country, region, city
FROM Sales.Customers
WHERE region <> N'WA';
SELECT custid, country, region, city
FROM Sales.Customers
WHERE region = NULL;
SELECT custid, country, region, city
FROM Sales.Customers
WHERE region IS NULL;
SELECT custid, country, region, city
FROM Sales.Customers
WHERE region <> N'WA'
OR region IS NULL;
---------------------------------------------------------------------
-- All-At-Once Operations
---------------------------------------------------------------------
/*
SELECT
orderid,
YEAR(orderdate) AS orderyear,
orderyear + 1 AS nextyear
FROM Sales.Orders;
*/
/*
SELECT col1, col2
FROM dbo.T1
WHERE col1 <> 0 AND col2/col1 > 2;
*/
/*
SELECT col1, col2
FROM dbo.T1
WHERE
CASE
WHEN col1 = 0 THEN 'no' -- or 'yes' if row should be returned
WHEN col2/col1 > 2 THEN 'yes'
ELSE 'no'
END = 'yes';
*/
/*
SELECT col1, col2
FROM dbo.T1
WHERE col1 <> 0 and col2 > 2*col1;
*/
---------------------------------------------------------------------
-- Working with Character Data
---------------------------------------------------------------------
---------------------------------------------------------------------
-- Collation
---------------------------------------------------------------------
SELECT empid, firstname, lastname
FROM HR.Employees
WHERE lastname = N'davis';
SELECT empid, firstname, lastname
FROM HR.Employees
WHERE lastname COLLATE Latin1_General_CS_AS = N'davis';
---------------------------------------------------------------------
-- Operators and Functions
---------------------------------------------------------------------
-- Concatenation
SELECT empid, firstname + N' ' + lastname AS fullname
FROM HR.Employees;
-- Listing 2-7: Query Demonstrating String Concatenation
SELECT custid, country, region, city,
country + N',' + region + N',' + city AS location
FROM Sales.Customers;
SET CONCAT_NULL_YIELDS_NULL OFF;
SET CONCAT_NULL_YIELDS_NULL ON;
SELECT custid, country, region, city,
country + N',' + COALESCE(region, N'') + N',' + city AS location
FROM Sales.Customers;
-- Functions
SELECT SUBSTRING('abcde', 1, 3); -- 'abc'
SELECT RIGHT('abcde', 3); -- 'cde'
SELECT LEN(N'abcde'); -- 5
SELECT DATALENGTH(N'abcde'); -- 10
SELECT CHARINDEX(' ','Itzik Ben-Gan'); -- 6
SELECT PATINDEX('%[0-9]%', 'abcd123efgh'); -- 5
SELECT REPLACE('1-a 2-b', '-', ':'); -- '1:a 2:b'
SELECT empid, lastname,
LEN(lastname) - LEN(REPLACE(lastname, 'e', '')) AS numoccur
FROM HR.Employees;
SELECT REPLICATE('abc', 3); -- 'abcabcabc'
SELECT supplierid,
RIGHT(REPLICATE('0', 9) + CAST(supplierid AS VARCHAR(10)),
10) AS strsupplierid
FROM Production.Suppliers;
SELECT STUFF('xyz', 2, 1, 'abc'); -- 'xabcz'
SELECT UPPER('Itzik Ben-Gan'); -- 'ITZIK BEN-GAN'
SELECT LOWER('Itzik Ben-Gan'); -- 'itzik ben-gan'
SELECT RTRIM(LTRIM(' abc ')); -- 'abc'
---------------------------------------------------------------------
-- LIKE Predicate
---------------------------------------------------------------------
-- Last name starts with D
SELECT empid, lastname
FROM HR.Employees
WHERE lastname LIKE N'D%';
-- Second character in last name is e
SELECT empid, lastname
FROM HR.Employees
WHERE lastname LIKE N'_e%';
-- First character in last name is A, B or C
SELECT empid, lastname
FROM HR.Employees
WHERE lastname LIKE N'[ABC]%';
-- First character in last name is A through E
SELECT empid, lastname
FROM HR.Employees
WHERE lastname LIKE N'[A-E]%';
-- First character in last name is not A through E
SELECT empid, lastname
FROM HR.Employees
WHERE lastname LIKE N'[^A-E]%';
---------------------------------------------------------------------
-- Working with Date and Time Data
---------------------------------------------------------------------
-- Literals
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate = '20070212';
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate = CAST('20070212' AS DATETIME);
SET LANGUAGE British;
SELECT CAST('02/12/2007' AS DATETIME);
SET LANGUAGE us_english;
SELECT CAST('02/12/2007' AS DATETIME);
SET LANGUAGE British;
SELECT CAST('20070212' AS DATETIME);
SET LANGUAGE us_english;
SELECT CAST('20070212' AS DATETIME);
SELECT CONVERT(DATETIME, '02/12/2007', 101);
SELECT CONVERT(DATETIME, '02/12/2007', 103);
-- Working with Date and Time Separately
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate = '20070212';
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate >= '20070212'
AND orderdate < '20070213';
SELECT CAST('12:30:15.123' AS DATETIME);
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE YEAR(orderdate) = 2007;
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate >= '20070101' AND orderdate < '20080101';
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE YEAR(orderdate) = 2007 AND MONTH(orderdate) = 2;
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate >= '20070201' AND orderdate < '20070301';
-- Functions
-- Current Date and Time
SELECT
GETDATE() AS [GETDATE],
CURRENT_TIMESTAMP AS [CURRENT_TIMESTAMP],
GETUTCDATE() AS [GETUTCDATE],
SYSDATETIME() AS [SYSDATETIME],
SYSUTCDATETIME() AS [SYSUTCDATETIME],
SYSDATETIMEOFFSET() AS [SYSDATETIMEOFFSET];
SELECT
CAST(SYSDATETIME() AS DATE) AS [current_date],
CAST(SYSDATETIME() AS TIME) AS [current_time];
-- CAST and CONVERT
SELECT CAST('20090212' AS DATE);
SELECT CAST(SYSDATETIME() AS DATE);
SELECT CAST(SYSDATETIME() AS TIME);
SELECT CONVERT(CHAR(8), CURRENT_TIMESTAMP, 112);
SELECT CAST(CONVERT(CHAR(8), CURRENT_TIMESTAMP, 112) AS DATETIME);
SELECT CONVERT(CHAR(12), CURRENT_TIMESTAMP, 114);
SELECT CAST(CONVERT(CHAR(12), CURRENT_TIMESTAMP, 114) AS DATETIME);
-- SWITCHOFFSET
SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), '-05:00');
SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), '+00:00');
-- TODATETIMEOFFSET
SELECT TODATETIMEOFFSET(SYSDATETIMEOFFSET(), '-05:00');
SELECT TODATETIMEOFFSET(SYSDATETIME(), '-05:00');
-- DATEADD
SELECT DATEADD(year, 1, '20090212');
-- DATEDIFF
SELECT DATEDIFF(day, '20080212', '20090212');
SELECT
DATEADD(
day,
DATEDIFF(day, '20010101', CURRENT_TIMESTAMP), '20010101');
SELECT
DATEADD(
month,
DATEDIFF(month, '20010101', CURRENT_TIMESTAMP), '20010101');
SELECT
DATEADD(
month,
DATEDIFF(month, '20091231', CURRENT_TIMESTAMP), '20091231');
-- DATEPART
SELECT DATEPART(month, '20090212');
-- DAY, MONTH, YEAR
SELECT
DAY('20090212') AS theday,
MONTH('20090212') AS themonth,
YEAR('20090212') AS theyear;
-- DATENAME
SELECT DATENAME(month, '20090212');
SELECT DATENAME(year, '20090212');
-- ISDATE
SELECT ISDATE('20090212');
SELECT ISDATE('20090230');
---------------------------------------------------------------------
-- Querying Metadata
---------------------------------------------------------------------
-- Catalog Views
USE TSQLFundamentals2008;
SELECT SCHEMA_NAME(schema_id) AS table_schema_name, name AS table_name
FROM sys.tables;
SELECT
name AS column_name,
TYPE_NAME(system_type_id) AS column_type,
max_length,
collation_name,
is_nullable
FROM sys.columns
WHERE object_id = OBJECT_ID(N'Sales.Orders');
-- Information Schema Views
SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = N'BASE TABLE';
SELECT
COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH,
COLLATION_NAME, IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = N'Sales'
AND TABLE_NAME = N'Orders';
-- System Stored Procedures and Functions
EXEC sys.sp_tables;
EXEC sys.sp_help
@objname = N'Sales.Orders';
EXEC sys.sp_columns
@table_name = N'Orders',
@table_owner = N'Sales';
EXEC sys.sp_helpconstraint
@objname = N'Sales.Orders';
SELECT
SERVERPROPERTY('ProductLevel');
SELECT
DATABASEPROPERTYEX(N'TSQLFundamentals2008', 'Collation')
SELECT
OBJECTPROPERTY(OBJECT_ID(N'Sales.Orders'), 'TableHasPrimaryKey');
SELECT
COLUMNPROPERTY(OBJECT_ID(N'Sales.Orders'), N'shipcountry', 'AllowsNull');